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

2 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'';
      };
    };

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