Can Home Manager install unstable and stable programs (modules) not just pkgs?

I’ve worked out how to do this with packages, but not programs.

I’m using Home Manager stable by default, and have installed mise as an unstable package (not available in nixpkgs stable, yet):

home.nix


{ pkgs, inputs, ... }: 

let

  unstable = import inputs.nixpkgs-unstable {
    system = pkgs.system;
  };

in

 {
    home = {
      enableNixpkgsReleaseCheck = true;
      stateVersion = "23.11";
      packages = with pkgs; [

        pkgs.unstable.mise

        bandwhich
        curl
        curlie
        ...

But I cannot install mise unstable as a module using pkgs.mise.unstable or pkgs.unstable.mise as per below.

mise.nix

{ config, pkgs, libs, ... }:
{

  programs.mise = {
    enable = true;
    package = pkgs.unstable.mise;
    #package = pkgs.mise.unstable;
    ...

pkgs.unstable.mise as I use above ( and works just as a package, not program/module) gives:

error: The option `home-manager.users.xxxx.programs.mise' does not exist.

pkgs.mise.unstable gives:

error: attribute 'mise' missing

           12|     package = pkgs.mise.unstable;                                                                                                   │
             |               ^                                                                                                                     │
           13|     enableZshIntegration = true;                                                                                                    │
       Did you mean one of muse, aide, brise, cvise or dive?

In…

https://nix-community.github.io/home-manager/options.xhtml

an example of the above (that I assume works) is:


services.lorri.nixPackage

    Which nix package to use.

    Type: package

    Default: pkgs.nix

    Example: pkgs.nixVersions.unstable

    Declared by:
    <home-manager/modules/services/lorri.nix>

muse, aide, brise, cvise or dive as per the error message above, are all available as both stable and unstable nixpkgs.

What I don’t understand, is why Home Manager can’t find the unstable nixpkg of mise to be installed as a program, yet it can install it as an unstable pkg.

You are using stable home manager and programs.mise exsists only in unstable. Unlike packages, “programs” are a concept from modules so they needa different approach if you want to mix stable and unstable modules. There’s an approach for a different unstable module in this thread.

1 Like

Thanks @VTimofeenko,

I’m trying to understand the solution from the post you have referred to:

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

...

home-manager.users.alice =
  _: # { config, ... }: # config is home-manager's config, not the OS one
  {
    imports = [ (inputs.home-manager-unstable + "/modules/programs/bemenu.nix") ];
    home.stateVersion = "23.11";
    programs.bemenu.enable = true;
  };

in my context:

flake.nix (nix-darwin) with home manager module > home.nix (home manager config) > mise.nix, which lilkely would be easy to implement…

but I have started using umport Umport: Automatic Import of Modules, and as noob, I do not know how to get around what appears to be a limitation to just 1 use of imports per .nix file or just home manager config, to use imports as you have or to integrate it into my existing import of all my modules betow…

 imports = ylib.umport {
    paths = [./pkgs-home-manager/modules-macos-active ./options-home-manager];
    recursive = true;
  };

I have tried to add the following to imports = ylib.umport { as per its API, but it (obviously) gives an error:

include = [ (inputs.home-manager-unstable + "./pkgs-home-manager/modules-macos-active/cli/mise/mise.nix") ];

If not possible via umport (likely - another - question I must write it’s author), is there another way to import mise.nix equivalent of your solution from the other post re bemenu?

I don’t have experience with umport, but imports generally is a list of modules, so try something like:

imports = (ylib.umport {
    paths = [./pkgs-home-manager/modules-macos-active ./options-home-manager];
    recursive = true;
  })
++
[ {reference to mise module from home-manager-unstable} ]
;

The exact text of the reference would depent on how reference to home-manager-unstable is passed to the file with the imports statement.

1 Like

Thanks @VTimofeenko,

This is amazing help from you (I will heart every comment once I’ve solved this). I’ve read through the post you linked to and here’s the error I’m getting after creating a reference to the mise module from home-manager-unstable:

error: access to absolute path '/nix/store/a7idmrymwccm7gnssm2hb04f6yk2mz9c-source./pkgs-home-manager/modules-macos-active/cli/mise/mise.nix' is forbidden in pure eval mode (use '--impure' to override)

How to otherwise reference the path to mise.nix to avoid this error?

flake.nix (nix-darwin)

inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-23.11-darwin";
    nixpkgs-unstable.url = "github:NixOs/nixpkgs/nixpkgs-unstable";
    home-manager.url = "github:nix-community/home-manager/release-23.11";
    home-manager.inputs.nixpkgs.follows = "nixpkgs";

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

outputs = inputs@{ self, nixpkgs, nixpkgs-unstable, home-manager-unstable, ...

let
    unstableOverlay = final: prev: {
      unstable = import nixpkgs-unstable {
       system = "aarch64-darwin";
      };
    };
    hmunstableOverlay = final: prev: {                              <---
      hmunstable = import home-manager-unstable {
       system = "aarch64-darwin";
      };
    };
   ylib = nypkgs.lib.aarch64-darwin;
    configuration = { pkgs, ... }: {
  ...
  nixpkgs = {
        hostPlatform = "aarch64-darwin";
          # The platform the configuration will be used on.
        config = { allowUnfree = true; };
          # Allow unfree software to be installed by Nix.
        overlays = [
          nur.overlay
            # For Firefox.
          unstableOverlay
            # For nixpkgs-unstable.
          hmunstableOverlay                                        <---
           # For home-manager-unstable.
          
        ];
      };
  ...

home.nix (home manager)

{ pkgs, inputs, ylib, ... }: 

let

  unstable = import inputs.nixpkgs-unstable {
    system = pkgs.system;
    # Uncomment this if you need an unfree package from unstable.
    #config.allowUnfree = true;
  };
  hmunstable = import inputs.home-manager-unstable {                <---
    system = pkgs.system;
    # Uncomment this if you need an unfree package from unstable.
    #config.allowUnfree = true;
  };

  in

  {
    home = {
      ... 
    };

  imports = (ylib.umport {
    paths = [./pkgs-home-manager/modules-macos-active ./options-home-manager];
    exclude = [./pkgs-home-manager/modules-macos-active/cli/mise/mise.nix ./pkgs-home-manager/modules-macos-active/cli/git/gitignore-global.nix ./pkgs-home-manager/modules-macos-active/gui/firefox/firefox-bookmarks.nix];
    recursive = true;
  })
  ++
  [ (inputs.home-manager-unstable + "./pkgs-home-manager/modules-macos-active/cli/mise/mise.nix") ] 
  ;

You would need to reference mise module from home-manager-unstable, not the local flake, like so (mind the absence of the dot):

-- [ (inputs.home-manager-unstable + "./pkgs-home-manager/modules-macos-active/cli/mise/mise.nix") ] 
++ [ (inputs.home-manager-unstable + "/modules/programs/mise.nix") ]

Also:

This would not work for modules since it’s a pattern that is used to create an instance of pkgs. Since there is no full code sample, I will not say that this statement can be removed or is harmful, but just FYI.

1 Like

Thanks @VTimofeenko, that makes sense, but I’m failing to fix this as I don’t know how to replace the hmunstable that is for pkgs as you say (the one you’ll see above it in the configs below - that I copied from - was used for pkgs.unstable.mise, which I have working in home.nix but want to replace with a module so I can declare versions of languages etc).

When I try your solution (ignoring replacing hmunstable, I get:

error: The option `programs.rtx.enable' can no longer be used since it's been removed. The `rtx` package has been replaced by `mise`, please switch over to
       using the options under `programs.mise.*` instead.

This is encouraging but the problem is, I am not refering to rtx anywhere in my configs. I previously did, but as the error says, mise is the new rtx.

Sidenote: Although everything works in my nix-darwin flake.nix > home manager home.nix setup (except the issue of this post), the only issue I’ve found so far is that there’s no Home Manager apps directory in /Applications or outside of /nix/store, which could be a sign I’ve stuffed something up. /Applications/Nix Apps exists, but is empty as I guess it’s only for nix-darwin installed modules, and I only have zsh installed that way. This could simply be a terminal permissions issue as I misclicked a terminal permission dialog when setting up the mac. Once I have this post’s issue fixed, I can look at doing a reset of macOS and reinstall of nix and my configs and hopefully everything will be fine. But if I’ve done something wrong (as you pointed out re my use of hmunstable), please correct me, and perhaps my configs will be fixed overall.

Here are all my paths and nix-darwin and home manager configs below:


~/.config/nix-darwin/flake.nix
~/.config/nix-darwin/nixpkgs/home.nix (home manager)
~/.config/nix-darwn/nixpkgs/pkgs-home-manager/modules-macos-active/
   eg ~/.config/nix-darwn/nixpkgs/pkgs-home-manager/modules-macos-active/cli/mise/mise.nix
   eg ~/.config/nix-darwn/nixpkgs/pkgs-home-manager/modules-macos-active/gui/firefox/firefox.nix

pkgs-home-manager and subdiretories are just for my organisational convenience and future admin by someone else for installing .nix home manager modules, and I’ll have a parallel directory pkgs-nix-darwin if I install any via it. I have zsh installed via it currently, but soon that will be moved to home manager with its own config.

flake.nix (nix-darwin)

{
  description = "xxxx nix-darwin flake";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-23.11-darwin";
    nixpkgs-unstable.url = "github:NixOs/nixpkgs/nixpkgs-unstable";

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

    home-manager-unstable.url = "github:nix-community/home-manager";
   # I add the below to copy the stable version above - not sure if necessary:
    home-manager-unstable.inputs.nixpkgs.follows = "nixpkgs-unstable";

    nix-darwin.url = "github:LnL7/nix-darwin";
    nix-darwin.inputs.nixpkgs.follows = "nixpkgs";

    nur.url = "github:nix-community/NUR";

    # For umport:
    nypkgs.url = "github:yunfachi/nypkgs";
    nypkgs.inputs.nixpkgs.follows = "nixpkgs";

    nix-homebrew.url = "github:zhaofengli-wip/nix-homebrew";
    homebrew-core = {
      url = "github:homebrew/homebrew-core";
      flake = false;
    };
    homebrew-cask = {
      url = "github:homebrew/homebrew-cask";
      flake = false;
    };
    homebrew-bundle = {
      url = "github:homebrew/homebrew-bundle";
      flake = false;
    };
  };

  outputs = inputs@{ self, nixpkgs, nixpkgs-unstable, home-manager-unstable, nix-darwin, nur, home-manager, nypkgs, nix-homebrew, homebrew-core, homebrew-cask, ... }:

  let

    unstableOverlay = final: prev: {
      unstable = import nixpkgs-unstable {
       system = "aarch64-darwin";
      };
    };
    hmunstableOverlay = final: prev: {
      hmunstable = import home-manager-unstable {
       system = "aarch64-darwin";
      };
    };

   # For umport:
    ylib = nypkgs.lib.aarch64-darwin;

    configuration = { pkgs, ... }: {

      environment.systemPackages = [ ];
      services.nix-daemon.enable = true;

      nix = {
        extraOptions = ''
          extra-platforms = x86_64-darwin aarch64-darwin
        '';
        linux-builder = {
          enable = true;
          ephemeral = true;
          maxJobs = 4;
          config = {
            virtualisation = {
              darwin-builder = {
                diskSize = 40 * 1024;
                memorySize = 8 * 1024;
              };
              cores = 4;
            };
          };
          # nix.package = pkgs.nix;
        };
        settings = {
          experimental-features = "nix-command flakes";
            # Necessary for using flakes on this system.
          trusted-users = [ "xxxx" ];
            # Necessary for linux-builder.
        };
      };

      programs.zsh.enable = true;  # default shell on catalina
        # Create /etc/zshrc that loads the nix-darwin environment.

      system = {
        configurationRevision = self.rev or self.dirtyRev or null;
          # Set Git commit hash for darwin-version.
        stateVersion = 4;
          # Used for backwards compatibility, please read the changelog before changing:`$ darwin-rebuild changelog`
      };

      nixpkgs = {
        hostPlatform = "aarch64-darwin";
          # The platform the configuration will be used on.
        config = { allowUnfree = true; };
          # Allow unfree software to be installed by Nix.
        overlays = [
          nur.overlay
            # For Firefox.
          unstableOverlay
            # For nixpkgs-unstable.
          hmunstableOverlay
        ];
      };

      imports = [ ./options-nix-darwin/options-nix-darwin.nix ];
        # eg settings to change dock location etc.

      homebrew = {
        enable = true;
        onActivation = {
          autoUpdate = true;
          cleanup = "zap";
          upgrade = false;
        };
        global.autoUpdate = false;
        brews = [ ];
        caskArgs.no_quarantine = true;
        casks = [ "amethyst" "firefox" ];
      };

    }; # /configuration

  in

    {
    darwinConfigurations."myhostname" = nix-darwin.lib.darwinSystem {

      specialArgs = { inherit inputs; inherit ylib; };

      modules = [
        configuration

        home-manager.darwinModules.home-manager {
          home-manager = {
            useGlobalPkgs = true;
            useUserPackages = true;
            users.xxxx = import ./nixpkgs/home.nix;
            extraSpecialArgs = { inherit inputs ylib; };
          };
          users.users.xxxx.home = "/Users/xxxx";
        }

        nix-homebrew.darwinModules.nix-homebrew {
          nix-homebrew = {
            enable = true;
            enableRosetta = true;
              # Apple Silicon Only: Also install Homebrew under the default Intel prefix for Rosetta 2
            user = "xxxx";
            taps = {
              "homebrew/homebrew-core" = homebrew-core;
              "homebrew/homebrew-cask" = homebrew-cask;
              "homebrew/homebrew-bundle" = inputs.homebrew-bundle;
            };
            mutableTaps = false;
              # Optional: Declarative tap management. If disabled, taps can't be added imperatively via `brew tap`.
          };
        }

      ];

    }; # /darwinConfigurations

    darwinPackages = self.darwinConfigurations."myhostname".pkgs;
      # Expose the package set, including overlays, for convenience.
  };
}

home.nix (home manager)

{ pkgs, inputs, ylib, ... }: 

let

  unstable = import inputs.nixpkgs-unstable {
    system = pkgs.system;
    # Uncomment this if you need an unfree package from unstable.
    #config.allowUnfree = true;
  };
  hmunstable = import inputs.home-manager-unstable {
    system = pkgs.system;
    # Uncomment this if you need an unfree package from unstable.
    #config.allowUnfree = true;
  };

in

  {
    home = {
      enableNixpkgsReleaseCheck = true;
      stateVersion = "23.11";
      packages = with pkgs; [
        #pkgs.unstable.mise
        bandwhich
        curl
        curlie
        ...
        lunarvim
      ];
  };

  editorconfig = {
    enable = false;
    settings = {
      "*" = {
        charset = "utf-8";
        end_of_line = "lf";
        trim_trailing_whitespace = true;
        insert_final_newline = true;
        max_line_width = 78;
        indent_style = "space";
        indent_size = 2;
      };
    };
  };

  fonts.fontconfig.enable = true;

  manual = {
    html.enable = true;
    json.enable = true;
    manpages.enable = true;
  };

  programs.home-manager.enable = true;
  programs.home-manager.path = "$HOME/.config/nix-darwin/nixpkgs/";

  imports = (ylib.umport {
    paths = [./pkgs-home-manager/modules-macos-active ./options-home-manager];
    exclude = [./pkgs-home-manager/modules-macos-active/cli/mise/mise.nix ./pkgs-home-manager/modules-macos-active/cli/git/gitignore-global.nix ./pkgs-home-manager/modules-macos-active/gui/firefox/firefox-bookmarks.nix];
    recursive = true;
  })
  ++
  [ (inputs.home-manager-unstable + "modules-macos-active/cli/mise/mise.nix") ] 
  ;

From a cursory glance at the module in question, this is triggered by this bit of code in mise.nix and is a consequence of mixing stable home-manager with unstable modules. Stable home-manager brings in the programs.rtx option and unstable module mise.nix “runs”[^1] a check that sees programs.rtx in the options and complains about it.

I see three ways from here:

  1. (probably easiest) Inline the mise.nix module by copying all parts except for the ones that emit warnings into a local file. Release 24.05 should be out within the next couple of months.
  2. (also easy) move to fully unstable inputs for home-manager and nixpkgs
  3. (may require some work) use disableModules option. There are some closed bugs for home-manager interaction.

That’s actually brought in by (comment mine):

unstableOverlay = final: prev: {
      unstable = import nixpkgs-unstable { # This effectively adds pkgs.unstable.* packages
       system = "aarch64-darwin";
      };
    };

As for the apps:

I am not using nix-darwin so have no idea here :slight_smile: This is mist likely a separate thing from the home-manager modules. Nuking MacOS to fix this would be a bit of an overkill IMHO.

[^1]: in reality it’s not mise.nix that runs anything. This check is run by nix itself when it’s evaluating the modules in a giant merge

1 Like

Thanks @VTimofeenko, I think it’s best I get back to development (using mise) by using the unstable pkg as I had set up, and then move to using the stable module in the 24.05 release, otherwise I’ll likely be circling this issue for longer. Thanks for outlining all my options!

Otherwise, the disableModules option looks best for now, and it’s good to know it exists as it provides a lot of flexibility I can use when more confident.

Oh, I agree - normally reinstalling an OS to fix a permissions issue would be a waste of time, but I was planning to reinstall macOS and my nix setup to test it on a clean machine (not just VM) anyways, so I’m interested to see if I did misclick a terminal permission (although I can’t find anything in the OS settings to show that).

I’ve learned a lot from you and will keep an eye out for your comments in this forum as you sure do know Nix. Many thanks, you are a great member of this community!

1 Like

@pedorich-n I’m not sure you can help (eg change anything until mise stable is released), but tagging you in just in case (and thanks for bringing mise to Nix!).

by using the unstable pkg as I had set up

Yeah, that would be option #4 that I should had mentioned :slight_smile:

I haven’t tried it myself, but I would say using the disabledModules is the way to go, as it’s the recommended way of disabling modules in NixOS: docs and it looks like Home Manager supports this attribute as well, see 1, 2, 3.

Something like:

{ config, inputs, pkgs-unstable, modulesPath, ...}: {
  disabledModules = [ "${modulesPath}/programs/mise.nix" ];

  imports = [ "${inputs.home-manager-unstable}/modules/programs/mise.nix" ];

  config = {
    programs.mise = {
      enable = true;
      package = pkgs-unstable.mise;
      ...
    };
  };
}

modulesPath is coming from here.

1 Like