Optimize flake.nix code

Hey, how can I make this flake as concise as possible? I have quite a few duplications in there. I thought of using a function to generate the nixosConfiguration blocks, so I only have to write it once. How would you make it as good as possible? If you see anything that is not best practice in there, please let me know as well:

{
  description = "NixOS configuration";

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

  outputs = { nixpkgs, home-manager, ... }: {
    nixosConfigurations = {
      pc = nixpkgs.lib.nixosSystem {
        system = "x86_64-linux";
        modules = [
          ./nixos-configurations/pc
          home-manager.nixosModules.home-manager
          {
            home-manager = {
              useGlobalPkgs = true;
              useUserPackages = true;
            };
          }
        ];
      };
      laptop = nixpkgs.lib.nixosSystem {
        system = "x86_64-linux";
        modules = [
          ./nixos-configurations/laptop
          home-manager.nixosModules.home-manager
          {
            home-manager = {
              useGlobalPkgs = true;
              useUserPackages = true;
            };
          }
        ];
      };
    };
  };
}

Some helper that would wrap the nixosSystem call is a common idiom, and you can push it to any level abstraction you want.

From a simple one that only takes the hostname or main entrypoint file, up to something where you can override every little bit of it.

Or the ultimate level of abstraction is a flake parts module that lets you configure even more, and does not only produce legitimate nixosConfiguration entries but also appropriate package outputs that can be used as images or to nix copy to a remote deployment target as well as checks or hydraChecks.

What level of abstraction you need here is hard to say now.

But as a starter, you can use this traditional mkSystem implementation:

mkSystem = entrypoint: nixpkgs.lib.nixosSystem {
  system = "x86_64-linux";
  modules = [
    entrypoint
    home-manager.nixosModules.home-manager
    {
      home-manager = {
        useGlobalPkgs = true;
        useUserPackages = true;
      };
    }
  ];
};

You could use that then like this:

pc = mkSystem ./nixos-configurations/pc;
laptop = mkSystem ./nixos-configurations/laptop;
2 Likes

yep, this looks almost exactly like what I planned to do. Thank you @NobbZ :slight_smile: