Home Manager across different OSs

Hi everyone,

I’m using NixOS on my desktop machine and home server, Ubuntu on my work laptop, and macOS on my personal laptop.
I’m using flakes for both NixOS and home-manager.
I can’t find a way to set my flakes up such that my main nixos flake uses the home-manager flake… Maybe I’m not understanding correctly and this isn’t actually possible? I’ve been trying to imitate it best I can by adding the home-manager module while using my personal home-manager flake as an input to import the same configurations (modules, extraSpecialArgs and such), but for some reason it doesn’t even seem to evaluate.

If anyone can shed some light on how this can be done (or refer me to another post that explains it) it would be greatly appreciated.

This is what I’ve come to currently (which doesn’t evaluate home.nix at all):
/etc/nixos/flake.nix

{
  description = "Main NixOS flake";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    home-manager = {
      url = "github:nix-community/home-manager";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    nur = {
      url = "github:nix-community/NUR";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    my-home.url = "path:/home/user/.config/home-manager";
  };

  outputs =
    {
      self,
      nixpkgs,
      home-manager,
      nur,
      my-home,
      ...
    }:
    {
      nixosConfigurations.desktop = nixpkgs.lib.nixosSystem {
        system = "x86_64-linux";
        modules = [
          ./system/configuration.nix
          ./modules/gaming.nix
          ./modules/backup.nix
          ./modules/hyprland.nix
          ./modules/vm.nix
          nur.modules.nixos.default
          home-manager.nixosModules.home-manager
          (
            let
              desktopInput = my-home.outputs.configurationInput "desktop";
              extraSpecialArgs = desktopInput.extraSpecialArgs // {
                pkgs = desktopInput.pkgs;
              };
              modules = desktopInput.modules;
            in
            {
              home-manager = {
                useGlobalPkgs = false;
                useUserPackages = true;

                users.user.imports = modules;
                inherit extraSpecialArgs;
              };
            }
          )
        ];
      };
    };
}

/home/user/.config/home-manager/flake.nix

{
  description = "My Home Manager configuration";

  inputs = {
    nixpkgs.url = "nixpkgs/nixpkgs-unstable";
    nixgl.url = "github:nix-community/nixGL";
    home-manager = {
      url = "github:nix-community/home-manager/master";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    nur = {
      url = "github:nix-community/NUR";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs =
    {
      nixpkgs,
      home-manager,
      nixgl,
      nur,
      ...
    }:
    let
      lib = nixpkgs.lib;
      system = "x86_64-linux";
      configurationInput =
        host:
        let
          conf = import ./hosts/${host}/conf.nix;
        in
        {
          pkgs = import nixpkgs {
            inherit system;
            config.allowUnfreePredicate = pkg: builtins.elem (nixpkgs.lib.getName pkg) conf.unfree;
            overlays = [ nur.overlays.default ];
          };
          modules = [ ./home.nix ];
          extraSpecialArgs = {
            inherit host;
            inherit system;
            hostConf = conf;
          }
          // (if !conf.isNixOS then { inherit nixgl; } else { });
        };
    in
    {
      homeConfigurations = {
        desktop = home-manager.lib.homeManagerConfiguration configurationInput "desktop";
        server = home-manager.lib.homeManagerConfiguration configurationInput "server";
        work = home-manager.lib.homeManagerConfiguration configurationInput "work";
      };

      inherit configurationInput;
    };
}

I’m sure there are probably several unconventional things / bad practices in here… I’m still learning… but I feel if I can get nixos to use the standalone home-manager I’d have an easier time tinkering and improving from there (that said, feel free to comment other improvements you think I can make if you feel like it).

I think I’m a bit confused about what you want. From the home-manager docs:

Home Manager is compatible with Nix Flakes. But please be aware that this support is still experimental and may change in backwards incompatible ways.

Just like in the standard installation you can use the Home Manager flake in three ways:

  1. Using the standalone home-manager tool. For platforms other than NixOS and Darwin, this is the only available choice. It is also recommended for people on NixOS or Darwin that want to manage their home directory independently of the system as a whole. See Standalone setup for instructions on how to perform this installation.
  2. As a module within a NixOS system configuration. This allows the user profiles to be built together with the system when running nixos-rebuild. See NixOS module for a description of this setup.
  3. […nix-darwin…]

It sounds like you are trying to mix options 1 and 2. Can you be more specific about what you are trying to accomplish and in what ways using just one or the other doesn’t achieve your goals?

I imagined a setup where when using nixos-rebuild switch on NixOS then home-manager gets evaluated automatically (which seems like option 2), but I also want to use the same home-manager setup (files) I use on other non-NixOS machines (which seems like option 1).

Can you just follow Option 2, with your home-manager config located within a subfolder of your nixos-config? In other words, you nix run home-manager/master -- init ./path/to/subfolder and set your NixOS configuration per Option 2 with home-manager.users.fqvtscrb = ./path/to/generated/home.nix?

On other systems you will git checkout your full nixos-config, and symlink appropriately $HOME/.config/home-manager to ./path/to/subfolder, thus allowing you to use standalone.

You can reuse the same HM configuration both standalone and as part of nixos/nix-darwin config. This is what I have in my flake.

If you need a standalone, you use homeConfigurations. Otherwise, your nixosConfigurations and darwinConfigurations import the same configuration using their respective HM modules.

What is different between deployments is (largely…) not the configuration itself but the supporting HM modules you have to use for each scenario.

Standalone
Nixos
Darwin

That was my previous setup, but I find that if I need to change something in the extraSpecialArgs or pkgs configuration then I have to do it in two places: the home-manager flake and the nixos flake. I want to avoid that…

Assuming I use the standalone setup, with homeConfigurations, how do I then build the configuration? running nixos-rebuild doesn’t do it…

$ nix run nixpkgs#home-manager -- build --flake <flake-dir>#...
$ nix run nixpkgs#home-manager -- switch --flake <flake-dir>#...