Extract my machine’s hostname

Hi,

I want to extract my machine’s hostname to it in import paths in flake.nix. I have a pc and a laptop, and I have a repo to store their configurations in one repo.

For example, my pc’s hostname is MohamedDesktop and laptop’s hostname is MohamedLaptop. In my repo, I have a folder for the device-specific configuration.

.dotfiles
├── ...
├── device
    ├── MohamedDesktop
    │   └── configuration.nix
    ├── MohamedLaptop
        └── configuration.nix

In my flake, I want the MyHostname read my hostname

...
 nixosConfigurations.${MyHostname} = nixpkgs.lib.nixosSystem {
    ...
    modules = [
        ...
        ./device/${MyHostname}/configuration.nix
}

I tried to solve this problem by add the following:

let
  hostname = pkgs.runCommand "hostname" { buildInputs = [ pkgs.coreutils pkgs.hostname ]; } "hostname > $out";
  myHostname = lib.readFile hostname;
in

But it returns localhost.

I will appreciate any help.

Quickest way to get this is a variation of this code:

nixosConfigurations.MohamedDesktop = 
+let
+  MyHostName = "MohamedDesktop";
+in
nixpkgs.lib.nixosSystem {
    ...
    modules = [
+        { networking.hostName = MyHostName; } # This is an inline module
        ...
-        ./device/${MyHostname}/configuration.nix
+       (./. + "/devices/${hostName}/configuration.nix")
}

(Note the “./.” syntax for dynamically constructing a path)

If the hosts’ configuration are very close, you can reduce boilerplate like so:

  nixosConfigurations =
    let
      hostNames = [
        "MohamedDesktop"
        "MohamedLaptop"
      ];
      inherit (nixpkgs) lib; # for quick function access
      commonModules = [ ./common-module-1.nix ]; # Whatever modules are common
    in
    lib.pipe hostNames [
      (map (
        hostName:
        lib.nameValuePair hostName (
          lib.nixosSystem {
            modules =
              commonModules
              ++ [ { networking.hostName = hostName; } ] # Sets the hostname
              ++ [ (./. + "/devices/${hostName}/configuration.nix") ]; # Imports the per-host configuration.nix
          }
        )
      ))
      lib.listToAttrs
    ];

Here’s an example of my wrapper around nixosSystem that does a similar thing.

I tried to solve this problem by add the following:

That command is run in an isolated build environment that has no access to the real environment, so it’s producing stub values. While it is possible to make a pattern like that work, it’s not ideal as it breaks the pure evaluation of flakes.

If you want to access the hostname value in a module somewhere, you should refer to it as config.networking.hostName.

Note that imports does not have access to config because of the way NixOS modules are evaluated. imports are evaluated first before config is a thing.

2 Likes