nix-community / home-manager

Manage a user environment using Nix [maintainer=@rycee]
https://nix-community.github.io/home-manager/
MIT License
7.17k stars 1.85k forks source link

Flakes: per-system configuration #3075

Open wmertens opened 2 years ago

wmertens commented 2 years ago

With flakes, the system has to be embedded in the pkgs selection. Instead, it would be easier to reuse configurations across platforms by having a setup like apps and packages, where the second level is the system.

Then pkgs can be optional.

So a config would go from

    {
      homeConfigurations = {
        ${username} = home-manager.lib.homeManagerConfiguration rec {
          pkgs = nixpkgs.legacyPackages.${system};
          modules = [
            # ...
          ];
        };
      };
    };

to

    flake-utils.lib.eachDefaultSystem (system: {
      homeConfigurations = {
        ${username} = home-manager.lib.homeManagerConfiguration rec {
          modules = [
            # ...
          ];
        };
      };
    })

I suppose both configurations could be supported by checking if the current system is an attribute in the home-manager script

sepiabrown commented 2 years ago

I also want this feature!

bobvanderlinden commented 2 years ago

I also ran into this inconvenience. This part of my config became a bit strange due to this restriction: https://github.com/bobvanderlinden/nixos-config/blob/bdfd8d94def9dc36166ef5725589bf3d7ae2d233/flake.nix#L38-L46

It now also isn't possible to share this home-manager configuration with OSX.

nixos-discourse commented 2 years ago

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/improving-a-flake-nix-config-that-configures-home-manager/23389/2

ambroisie commented 2 years ago

Still relevant.

scottwillmoore commented 2 years ago

Okay, so I'm new to Nix, but I may have a solution.

When I ran home-manager switch --flake .#scott, with no exported homeConfigurations.scott, I got this output...

error: flake 'git+file:///home/scott/dotfiles' does not provide attribute 'packages.x86_64-linux.homeConfigurations."scott".activationPackage', 'legacyPackages.x86_64-linux.homeConfigurations."scott".activationPackage' or 'homeConfigurations."scott".activationPackage'.

So, I tried to export homeConfigurations.scott as packages.${system}.homeConfigurations.scott instead, and this does appear to work. I don't think this behaviour comes from home manager, but instead from the Nix CLI, when nix build is invoked by home manager which is somewhat documented.

The work around explained by @nixos-discourse will also work, with homeConfigurations."${system}-scott, although a little uglier.

It still might be an idea to consider support for homeConfigurations.${system}.scott, but this is up to the home manager contributors.

TL;DR: It appears that packages.${system}.homeConfigurations.scott will work.

bobvanderlinden commented 2 years ago

Meh, I do see it is a solution, but that shouldn't be a documented solution :sweat_smile: The suggestion from @wmertens still makes sense to me.

Especially new people shouldn't be placing home configuration into packages, as that adds to the already (sometimes) confusing Nix ecosystem.

roberth commented 1 year ago

The current interface seems fairly consistent with the attributes for NixOS, the idea being that a nixosConfigurations.<name> is as specific as it gets; typically a specific host. nixosModules.<name> on the other hand can be reused in any configuration that needs it, including different cpu architectures, etc.

Perhaps for your use case, an attribute like homeModules.<name> makes more sense, considering that you seem to want to use it in more than one configuration? This way the flake schema remains consistent with that of NixOS.

edrex commented 1 year ago

I think homeConfigurations is more like packages than nixosConfigurations. The reason each nixosConfiguration specifies system is that it is meant to run on specific hardware, whereas the point of hm is to make your home profile portable across hosts.

edrex commented 1 year ago

Unfortunately, the workaround detailed by @scottwillmoore doesn't work in a flake-parts context, since the option expects values of type package:

error: A definition for option `perSystem.x86_64-linux.packages.homeConfigurations' is not of type `package'.

Update: perSystem.legacyPackages does pass. This is what I did (it is terrible): https://github.com/edrex/nixcfg/commit/26230ced1794c32f7e8a62fc7664ecb04a6afe94#diff-206b9ce276ab5971a2489d75eb1b12999d4bf3843b7988cbe8d687cfde61dea0

Shados commented 1 year ago

The reason each nixosConfiguration specifies system is that it is meant to run on specific hardware, whereas the point of hm is to make your home profile portable across hosts.

homeConfigurations may also be specialised to specific hardware. For example, the HM config for my desktop has a number of differences compared to the config for my laptop, due to the difference in the number, size, resolution, and viewing distance of available monitors. The set of packages installed also varies between them, because they're used for different purposes.

Sharing configuration across homeConfigurations, and across a variety of systems, is already pretty trivial in a flake, for example I do something along the lines of:

{
  description = "Home Manager configuration of shados";

  inputs = {
    nixpkgs.url = "nixpkgs";
    home-manager = {
      url = github:nix-community/home-manager;
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = { nixpkgs, home-manager, ... } @ inputs:
    let
      mkHomeConfig = machineModule: system: home-manager.lib.homeManagerConfiguration {
        pkgs = import nixpkgs {
          inherit system;
        };

        modules = [
          ./sharedConfig
          machineModule
        ];

        extraSpecialArgs = {
          inherit inputs system;
        };
      };
    in {
      homeConfigurations."shados@desktop" = mkHomeConfig ./machine/desktop.nix "x86_64-linux";
      homeConfigurations."shados@laptop" = mkHomeConfig ./machine/laptop.nix "x86_64-linux";
      homeConfigurations."shados@work" = mkHomeConfig ./machine/work.nix "x86_64-darwin";
      homeConfigurations."shados@arm-vm" = mkHomeConfig ./machine/arm-vm.nix "aarch64-linux";
    };
}

Anything truly portable lives in the ./sharedConfig module (or its imported modules), and per-device config lives in files under ./machine.

If your HM config is intended to be 100% portable and identical across machines, you could get something pretty close to what @wmertens originally wanted:

      homeConfigurations = with nixpkgs.lib; listToAttrs (flip map flake-utils.lib.defaultSystems
        (system: nameValuePair "${username}-${system}" home-manager.lib.homeManagerConfiguration {
          pkgs = import nixpkgs { inherit system; };
          modules = [
            # ...
          ];
        }));

And then build with home-manager switch --flake ~/.config/home-manager#username-x86_64-linux, and drop the --flake option on subsequent calls, as per usual.


If anything, I would say a better change would be for home-manager.lib.homeManagerConfiguration to explicitly take a system argument and a bare nixpkgs argument, instead of an instantiated pkgs. This would bring HM more in line with nixpkgs, and I think this would also make it easier to fix #2942 & #2954...

martin-braun commented 1 year ago

Oh this was a pitfall. I was wondering why it was complaining

flake ... does not provide attribute 'packages.x86_64-linux.homeConfigurations." username".activationPackage', 'legacyPackages.x86_64-linux.homeConfigurations."username".activationPackage' or 'homeConfigurations."username".activationPackage'

because I didn't understand that the (standalone) home-manager acts like nixos-rebuild, but instead of picking the hostName from the nixosConfigurations, it picks the username from homeConfigurations.

So I have to home-manager switch --flake .#<username>-x86_64-linux to support multiple platforms, ahhh.

I don't understand why the system can't be read and used prior the flake resolve. That would make things easier, on system flakes as well.

x10an14 commented 1 year ago

(...) because I didn't understand that the (standalone) home-manager acts like nixos-rebuild, but instead of picking the hostName from the nixosConfigurations, it picks the username from homeConfigurations.

So I have to home-manager switch --flake .#<username>-x86_64-linux to support multiple platforms, ahhh.

I don't understand why the system can't be read and used prior the flake resolve. That would make things easier, on system flakes as well.

home-manager switch (without any other arguments) works for me when I have <path.to.flake>#homeConfigurations."$USER@$(hostname)".activationPackage?

Maybe because it (my HM nix setup/repo) always imports all HM modules for all systems (read: any configured Linux user/combo) through a home.nix in root of repo, but I didn't think it has to be that way had.

A symlink is needed though to ~/.config/home-manager, pointing to config repo I'm pretty sure.

martin-braun commented 1 year ago

@x10an14 I couldn't figure out how to do that. For me, it will always try to find the configuration of the username and only the username. I've seen a lot of configs that follow the $USER@$(hostname) scheme, but I couldn't pin point the key to toggle this behavior, unless passing '.#'$USER@${hostname}.

My situation is probably different and that might be relevant, because my configuration is strictly separated. My HM profile is a single-user multi-host configuration that I want to resolve by hostname only, similarly how Nix is doing it for the system flakes in /etc/nixos/ on sudo nixos-rebuild switch.

I think my recent issue #4246 is a dub, so I will quote myself:

It would be nice if I could tell the home-server in my configuration to look for the hostname instead of username in homeConfigurations. I know I can use the --flake attribute with #<hostname> to get what I want, but it adds necessary tooling that I feel could be solved within the configuration itself.

Why would I want that? Since we can store user configurations in $HOME, it's reasonable to maintain single-user repositories (one user per repo) for multiple hosts, instead of the common case to have a per-user (multi user) repo for many hosts, which often puts everything together (incl. system configuration).

Imho, user and system should be separated, even user and another user (different persons) should be separated. So for me personally, it would make sense if home-manager switch looks for homeConfiguration."<hostName>" instead of homeConfiguration."<username>".

Or why not just looking for homeConfiguration."<username>@<hostName>", then homeConfiguration."<username>", then homeConfiguration."<hostName>", in that order to give much flexibility. As soon as a configuration is found, it will be used.

Lastly, I want to emphasize that I don't like any work-arounds that require more abstraction and complexity. I'm happy to learn Flakes in their purest form, I don't want to involve additional abstractions, I even keep myself from defining any functions to re-use (i.e. mkHomeConfiguration) to keep the declaration flow as simple as possible, since I'm still learning.

For now, I will just have to pass more arguments to home-server, but hopefully my opinion will matter in the slightest. Perhaps one will acknowledge it as valuable feedback of new-comers and their problems adapting Nix in general, but I'm still too inexperienced to give a fundamental opinion to be honest.

Thank you.

stale[bot] commented 1 year ago

Thank you for your contribution! I marked this issue as stale due to inactivity. Please be considerate of people watching this issue and receiving notifications before commenting 'I have this issue too'. We welcome additional information that will help resolve this issue. Please read the relevant sections below before commenting.

If you are the original author of the issue

* If this is resolved, please consider closing it so that the maintainers know not to focus on this. * If this might still be an issue, but you are not interested in promoting its resolution, please consider closing it while encouraging others to take over and reopen an issue if they care enough. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.

If you are not the original author of the issue

* If you are also experiencing this issue, please add details of your situation to help with the debugging process. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.

Memorandum on closing issues

Don't be afraid to manually close an issue, even if it holds valuable information. Closed issues stay in the system for people to search, read, cross-reference, or even reopen – nothing is lost! Closing obsolete issues is an important way to help maintainers focus their time and effort.

ambroisie commented 1 year ago

Still relevant.

nixos-discourse commented 1 year ago

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/strategy-to-use-same-config-at-work-and-home/34317/4

stale[bot] commented 10 months ago

Thank you for your contribution! I marked this issue as stale due to inactivity. Please be considerate of people watching this issue and receiving notifications before commenting 'I have this issue too'. We welcome additional information that will help resolve this issue. Please read the relevant sections below before commenting.

If you are the original author of the issue

* If this is resolved, please consider closing it so that the maintainers know not to focus on this. * If this might still be an issue, but you are not interested in promoting its resolution, please consider closing it while encouraging others to take over and reopen an issue if they care enough. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.

If you are not the original author of the issue

* If you are also experiencing this issue, please add details of your situation to help with the debugging process. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.

Memorandum on closing issues

Don't be afraid to manually close an issue, even if it holds valuable information. Closed issues stay in the system for people to search, read, cross-reference, or even reopen – nothing is lost! Closing obsolete issues is an important way to help maintainers focus their time and effort.

jzbor commented 10 months ago

Still relevant.

stale[bot] commented 7 months ago

Thank you for your contribution! I marked this issue as stale due to inactivity. Please be considerate of people watching this issue and receiving notifications before commenting 'I have this issue too'. We welcome additional information that will help resolve this issue. Please read the relevant sections below before commenting.

If you are the original author of the issue

* If this is resolved, please consider closing it so that the maintainers know not to focus on this. * If this might still be an issue, but you are not interested in promoting its resolution, please consider closing it while encouraging others to take over and reopen an issue if they care enough. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.

If you are not the original author of the issue

* If you are also experiencing this issue, please add details of your situation to help with the debugging process. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.

Memorandum on closing issues

Don't be afraid to manually close an issue, even if it holds valuable information. Closed issues stay in the system for people to search, read, cross-reference, or even reopen – nothing is lost! Closing obsolete issues is an important way to help maintainers focus their time and effort.

zeorin commented 7 months ago

Still relevant.

stale[bot] commented 4 months ago

Thank you for your contribution! I marked this issue as stale due to inactivity. Please be considerate of people watching this issue and receiving notifications before commenting 'I have this issue too'. We welcome additional information that will help resolve this issue. Please read the relevant sections below before commenting.

If you are the original author of the issue

* If this is resolved, please consider closing it so that the maintainers know not to focus on this. * If this might still be an issue, but you are not interested in promoting its resolution, please consider closing it while encouraging others to take over and reopen an issue if they care enough. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.

If you are not the original author of the issue

* If you are also experiencing this issue, please add details of your situation to help with the debugging process. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.

Memorandum on closing issues

Don't be afraid to manually close an issue, even if it holds valuable information. Closed issues stay in the system for people to search, read, cross-reference, or even reopen – nothing is lost! Closing obsolete issues is an important way to help maintainers focus their time and effort.

Pamplemousse commented 3 months ago

Still relevant :smiling_face_with_tear:

soulomoon commented 1 month ago

Still relevant 🥲

FBIGlowie commented 1 month ago

still unrelevant

lz37 commented 3 weeks ago

Okay, so I'm new to Nix, but I may have a solution.

When I ran home-manager switch --flake .#scott, with no exported homeConfigurations.scott, I got this output...

error: flake 'git+file:///home/scott/dotfiles' does not provide attribute 'packages.x86_64-linux.homeConfigurations."scott".activationPackage', 'legacyPackages.x86_64-linux.homeConfigurations."scott".activationPackage' or 'homeConfigurations."scott".activationPackage'.

So, I tried to export homeConfigurations.scott as packages.${system}.homeConfigurations.scott instead, and this does appear to work. I don't think this behaviour comes from home manager, but instead from the Nix CLI, when nix build is invoked by home manager which is somewhat documented.

The work around explained by @nixos-discourse will also work, with homeConfigurations."${system}-scott, although a little uglier.

It still might be an idea to consider support for homeConfigurations.${system}.scott, but this is up to the home manager contributors.

TL;DR: It appears that packages.${system}.homeConfigurations.scott will work.

genus!!! it works