Get hostname in home-manager flake for host-dependent user configs

I have successfully flakified my system and HM config by making a flake (inspired by @gvolpe 's implementation) with

  ...
  outputs = inputs @ { self, nixpkgs, nurpkgs, nixpkgsUnstable, home-manager }:
    let
      system = "x86_64-linux";
    in
    {
      homeConfigurations = (
        import ./outputs/home-conf.nix {
          inherit system;
          inherit (inputs) nixpkgs nurpkgs nixpkgsUnstable home-manager;
        }
      );

      nixosConfigurations = (
        import ./outputs/nixos-conf.nix {
          inherit (nixpkgs) lib;
          inherit inputs system;
        }
      );
  ...

and in ./outputs/home-conf.nix

{ system, nixpkgs, nurpkgs, nixpkgsUnstable, home-manager, ... }:

let
  mkHome = username: (
    let
      homeDirectory = "/home/${username}"; # TODO: if darwin then /Users/${username}
      configHome = "${homeDirectory}/.config";

      pkgs = import nixpkgs {
        inherit system;
        config.allowUnfree = true;
        config.android_sdk.accept_license = true;
        config.xdg.configHome = configHome;
        overlays = [
          nurpkgs.overlay
        ] ++ (import ../home/${username}/overlays);
      };

      unstable = import nixpkgsUnstable {
        inherit system;
        config.allowUnfree = true;
        config.android_sdk.accept_license = true;
        config.xdg.configHome = configHome;
      };

      nur = import nurpkgs {
        inherit pkgs;
        nurpkgs = pkgs;
      };

      conf = (
        import ../home/${username}/home.nix {
        inherit nur pkgs unstable username homeDirectory;
        inherit (pkgs) config lib stdenv;
      });
    in
    home-manager.lib.homeManagerConfiguration rec {
      inherit pkgs system username homeDirectory;
      extraSpecialArgs = { inherit unstable; };
      stateVersion = "21.11";
      configuration = conf;
    });
in
{
  jeroen = mkHome "jeroen";
}

So far so good…

But now I need to override my generic home definitions with some host-specific ones. I refer to dotfiles and settings from ../home/${username}/home.nix like this:

  imports = [
    ../users-hm-common.nix # default packages for all users
    ./themes
  ] ++ (import ./programs)
    ++ (import ./services)

where the respective ./programs/default.nix is a list of references to subdirs like ./programs/autorandr/ with corresponding HM-config settings in its default.nix

But since things like autorandr are configured differently depending on host, my idea was to do something like this:

let
  hostDefaultNix = "default-${hostname}.nix";
in
{

  imports = [
    ../users-hm-common.nix # default packages for all users
    ./themes
  ] ++ (import ./programs) ++ (if builtins.pathExists ./programs/${hostDefaultNix} then import ./programs/${hostDefaultNix} else [])
    ++ (import ./services) ++ (if builtins.pathExists ./services/${hostDefaultNix} then import ./services/${hostDefaultNix} else []);

but for that I need to know the hostname that was set by this flake when doing

nixos-rebuild switch --use-remote-sudo --flake .#$(hostname -s)

when I build the HM config with

  nix build .#homeConfigurations.${USER}.activationPackage
  result/activate -b bak

How to achieve this?

BTW: to complete the transition I’d also need to get rid of the hard-coded system value from the main flake, since it should take the value of the host on which it is built. (I’m not considering remote builds for this setup)

2 Likes

Instead of checking the hostname within your configuration, use separate configurations. home-manager --flake will by default check for $USER@$(hostname) then $USER.

3 Likes

It should be explained in the manual: Home Manager Manual

The extra logic around managing user+hostname has gone undocumented though. The scripts for this are easy to read if you need more detail.

2 Likes

@NobbZ @TLATER Thanks a lot, you have very much enlightened me (as always) :smiley:

So (for posterity):

The activation for HM (with the same flake) I now do with just

home-manager switch --flake .

and in outputs/home.conf I have the

userx@hosty = mkHome "userx" "hosty"`

specified, and in the mkHome function I just inherit down hostname so the default/specific logic is handled for ./programs/ etc. as described above.

Happy camper here, very elegant solution now.

3 Likes