Mixing NixOS and HM modules

Hey there,

I’m trying to re-organize my config that uses both NixOS and Home-Manager configuration options by using NixOS modules. Ideally, I would only import each of the modules once. However, there are situations where I need to define both NixOS and Home-Manager options in one module (if I want to have only one module for each functionality).

An example for this would be a module for enabling zsh with my custom configuration options (which I set via Home-Manager):

NixOS option I have to set:

programs.zsh.enable = true;

Home-Manager option(s) I have to set:

programs.zsh.enable = true;
programs.zsh.enableCompletion = true;
...

The programs.zsh.* are not the same, but NixOS requires to set the shell system-wide.

How would one incorporate these options into one singular module? Is there a canonical way?

Regards,
Moritz

3 Likes

Yeah exactly the same situation for me. Also when using hyprland.

There is https://github.com/FlafyDev/combined-manager which (from my reading) does this for flakes, but it has some limitations that are currently dealbreakers for me.
There is a thread on this forum about it Combined Manager: New structure for personal NixOS configs - #4 by don.dfh

I am still wondering if there is a simpler solution to this question so that I don’t have configuration lines distributed over multiple files that are not logically connected.

I include the home-manager part into the NixOS modules, like this:

    services.usbmuxd.enable = true;
    environment.systemPackages = with pkgs;
      [
        libimobiledevice
      ];

    home-manager.users.${config.az-username} = {
      home.shellAliases = {
        iphone-backup = ''
          backup_dir=~/Downloads/$(date -I)_iphone &&
          mkdir -p $backup_dir &&
          ${pkgs.libimobiledevice}/bin/idevicebackup2 backup $backup_dir &&
          ${pkgs.gnutar}/bin/tar cjf $backup_dir.tar.bz2 $backup_dir &&
          rm -r $backup_dir'';

        ipad-backup = ''
          backup_dir=~/Downloads/$(date -I)_ipad &&
          mkdir -p $backup_dir &&
          ${pkgs.libimobiledevice}/bin/idevicebackup2 backup $backup_dir &&
          ${pkgs.gnutar}/bin/tar cjf $backup_dir.tar.bz2 $backup_dir &&
          rm -r $backup_dir'';
      };
    };
1 Like

Thanks for the example code.

I’ve dug around some more and this is my new understanding, plz correct me where wrong.

It seems the installation method matters, mine is flakes + nixosModule correct?
For the nixosModule and nixDarwin module there is osConfig which gives read access to a nixosConfiguration.
For the standalone installation method osConfig seems to be unavailable.

What I’m not sure I understand is, when using the nixosModule method, the evaluation of the user configuration happens within the evaluation of the nixosConfiguration, which is why osConfig is available - :crossed_fingers: this is correct?

Shouldn’t it be possible in this specific combination (from the perspective of nix internals) to also allow setting nixosConfiguration options from within a home-manager module because everything is evaluated at once?

No, what happens when using the home-manager NixOS module (or nix-darwin module), is that all the home-manager options are nested inside a sub-heirarchy inside the NixOS module options under the home-manager attribute. So programs.zsh and home-manager.users.me.programs.zsh are not the same thing.

What I think they want to do is:


home-manager.users.${config.az-username} = {
    osConfig.programs.zsh = true;
};

So it wouldn’t be the same thing and might in theory work but I don’t know if there’s something preventing it in practice and that’s why they made it read only in the first place.

1 Like

Yes, thanks for the code example @Nebucatnetzer that would be the ideal.

After some more poking around it seems the best way is to use a that determine if any user uses ZSH in their shell/ home-manager settings and set the system programs.zsh accordingly.

1 Like

It’s possible with flake-parts: flake-parts built in - flake-parts

{
  flake.modules = {
    nixos.zsh.programs.zsh.enable = true;
    homeManager.zsh = {
      programs.zsh = {
        enable = true;
        enableCompletion = true;
      };
    };
  };
}

Or try GitHub - srid/nixos-unified: Unify NixOS + nix-darwin + home-manager configuration in a single flake, while providing a consistent interface at DX and UX level. · GitHub

Please don’t necro-spam. I appreciate the intent is probably to make searching for solutions easier, but it spreads the discussion everywhere. You can link to other posts if you need to, like this (where I add context to your post and suggest something cleaner): One module that combines home manager and system packages? - #4 by TLATER

Other threads will automatically get backreferences.

1 Like