Hostname-agnostic nix-darwin configuration?

I’m looking at the output of the default flake.nix that’s create by nix-darwin

darwinConfigurations."Johns-MacBook" = nix-darwin.lib.darwinSystem {
  modules = [ configuration ];
};

Is there a way to define a default nix-darwin configuration so that a specific hostname (e.g., “Johns-Macbook”) doesn’t need to be specified when darwin-rebuild switch is called.

It should be based on your current host’s name.

Does “should” here mean that you think it would be a bad idea to leave the hostname unspecified, so that the configuration could match any hostname?

I’m with @imanllm in wanting to find a way to remove mention of specific hostnames from my configuration, and to only mention them if the need arises.

Yes, because every host is going to have differences. Create a common set of modules if you want.

Also a blank string won’t “match” all hostnames.

Reading the source today, I see that using the hostname is the fallback behavior, used only when the --flake flag value doesn’t satisfy the regular expression that looks for an expression after the octothorp (‘#’). That means that we can name the “darwinConfigurations” attribute something like “local”, and then supply, say, “.#local” as the --flake flag value.

But you missed my point, which is that generally, hosts are not identical.

I understand that, and I didn’t mean to suggest that hosts would be identical.

Rather, some of us would like to write configurations that we can share across many computers without concern for the current computer’s hostname. It turns out that nix-darwin anticipates this desire, but I haven’t found documentation that explains how to take advantage of it. The source code tells me that it’s a valid way to use it, though.

In my flake I have other places where I prefer to specify the variation between my machines, such that I don’t need multiple “darwinConfigurations” entries to capture that variation.

How exactly is that possible when they all have the same entrypoint? The same config would get built which makes that basically impossible unless you’re using --impure (which is bad practice for obvious reasons).

Your hostnames will differ, your hardware and even architectures will likely differ, your disk layout will almost certainly differ unless you’ve somehow ensured to use identical labels (which would necessitate that you never share disks) or share disks (which’d make it impossible to safely put the /nix/store on the shared disk because systems would GC each other).

I understand what you think you want, but it’s simply not a reasonable expectation.

Again, you can reuse code by writing modules that are shared - literally everything in the nix-darwin repo is an example of such shared modules that every nix-darwin system can use - but you want distinct entrypoints per host.

You may consider this technique to be cheating, but it’s possible by way of Git branches: I isolate the configuration for each machine on a Git branch that I (usually) don’t push to the upstream hosted repository. With that approach, the flake defines configuration for only one machine: the “current” machine. It does not accumulate the configuration for a fleet of machines, segregating them each by their hostnames (or some other differentiating identifier).

I borrowed this technique from @midchildan, per a discussion in their GitHub-hosted repository about two years ago. Granted, there they said that they do collect the configuration for several machines in one repository, but that they keep that repository private. I went a silghtly different direction, with the cloned Git repository on each machine storing its deviations from the common configuration.

Since I asked them about advice for technique in this area, they did integrate flake-parts into their repository, but I still have not adapted that transition into mine.

So you have a separate flake for each host. Fair enough, if that works for you.

Yes, I suppose so. That’s not how I think of it, but your description is accurate.

It may not be the best way to manage a small set of computers (two or three). I’ve been reluctant to publish the names and any other details of my work-related computers, nor to signal when those details change. Against that, though, I’ve had some encouragement to publish my Git repository publicly, so that colleagues of mine can borrow from it.

Here’s how I do it.

I have modules that take host and user variables (any particular module may not use them, but they’re available). Then I add a shell alias (fish, because I’m not an animal) that automatically populates the hostname from that variable:

Here’s how I pass those variables for NixOS systems: nixos-configs/flake.nix at a7d3976fa76e9c33841136c97d5290587359c83a · zmitchell/nixos-configs · GitHub

Here’s how I do it for my nix-darwin laptop: nixos-configs/flake.nix at a7d3976fa76e9c33841136c97d5290587359c83a · zmitchell/nixos-configs · GitHub

Here’s the alias: nixos-configs/homeConfigurations/common.nix at a7d3976fa76e9c33841136c97d5290587359c83a · zmitchell/nixos-configs · GitHub

In short, when I want to rebuild my system I just type drs<space> and it gets automatically expanded to sudo darwin-rebuild switch --flake .#chonker for my laptop.

If your host variable value (e.g. “chonker”) is the same as your computer’s reported hostname, then your shell alias doesn’t even need that host variable’s value; you could invoke sudo darwin-rebuild switch --flake ‘.#’ and darwin-rebuild will decide to look for a configuration with the current hostname.

Again, though, I’m not sure whether “chonker” is one of your computers’ hostnames.