Files
dotfiles/.agents/skills/nixos-best-practices/rules/flakes-structure.md
2026-02-05 18:47:42 +00:00

4.6 KiB

title, impact, impactDescription, tags
title impact impactDescription tags
Flakes Configuration Structure CRITICAL Foundation of flake-based NixOS configurations flakes,special-args,inputs,multiple-hosts

Why This Matters

A well-structured flake.nix makes it easy to manage multiple hosts, share common configurations, and maintain the codebase. Poor structure leads to duplication and confusion.

Core Structure

{
  description = "My NixOS configuration";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
    home-manager.url = "github:nix-community/home-manager/release-25.05";
    home-manager.inputs.nixpkgs.follows = "nixpkgs";
    # Add other flake inputs here
  };

  outputs = { self, nixpkgs, home-manager, ... }@inputs: {
    nixosConfigurations.hostname = nixpkgs.lib.nixosSystem {
      specialArgs = { inherit inputs; };
      modules = [ ./hosts/hostname ];
    };
  };
}

Special Args Pattern

Pass inputs via specialArgs to make flake inputs available in modules:

# ❌ WRONG: Forgetting specialArgs
outputs = { self, nixpkgs, home-manager }:
{
  nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
    modules = [ ./hosts/myhost ];  # inputs not available!
  };
}

# ✅ CORRECT: Using specialArgs
outputs = { self, nixpkgs, home-manager, ... }@inputs:
{
  nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
    specialArgs = { inherit inputs; };
    modules = [ ./hosts/myhost ];  # inputs available!
  };
}

Then use in modules:

# hosts/myhost/default.nix
{ inputs, pkgs, ... }:
{
  # Can now use inputs.*
  imports = [
    inputs.home-manager.nixosModules.home-manager
  ];
}

Input Following

Set inputs.nixpkgs.follows to avoid duplicate nixpkgs instances:

inputs = {
  nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";

  # ❌ WRONG: Doesn't follow, creates duplicate nixpkgs
  home-manager.url = "github:nix-community/home-manager/release-25.05";

  # ✅ CORRECT: Follows nixpkgs, uses same instance
  home-manager.url = "github:nix-community/home-manager/release-25.05";
  home-manager.inputs.nixpkgs.follows = "nixpkgs";
};

Multiple Hosts Pattern

outputs = { self, nixpkgs, home-manager, ... }@inputs: {
  # Define multiple hosts
  nixosConfigurations.laptop = nixpkgs.lib.nixosSystem {
    specialArgs = { inherit inputs; };
    modules = [ ./hosts/laptop ];
  };

  nixosConfigurations.desktop = nixpkgs.lib.nixosSystem {
    specialArgs = { inherit inputs; };
    modules = [ ./hosts/desktop ];
  };

  nixosConfigurations.server = nixpkgs.lib.nixosSystem {
    specialArgs = { inherit inputs; };
    modules = [ ./hosts/server ];
  };
};

System-Specific Packages

Pass system-specific args like pkgs-stable:

outputs = { self, nixpkgs, nixpkgs-stable, home-manager, ... }@inputs:
let
  system = "x86_64-linux";
in
{
  nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
    specialArgs = {
      inherit inputs system;
      pkgs-stable = import inputs.nixpkgs-stable {
        inherit system;
        config.allowUnfree = true;
      };
    };
    modules = [ ./hosts/myhost ];
  };
};

Usage in host config:

# hosts/myhost/default.nix
{ inputs, pkgs, pkgs-stable, system, ... }:
{
  environment.systemPackages = with pkgs; [
    unstable-package  # From nixos-unstable
  ];

  # Or use stable version
  environment.systemPackages = with pkgs-stable; [
    stable-package
  ];
}

Common Mistakes

  1. Not using @inputs pattern: Forgetting to capture all inputs in a set makes it impossible to reference new inputs without updating the function signature.

  2. Missing specialArgs: Inputs won't be available in modules without specialArgs = { inherit inputs; }.

  3. Hardcoded system: Avoid hardcoding x86_64-linux multiple times. Define once and reuse.

  4. Not following nixpkgs: Leads to multiple nixpkgs evaluations, slower builds, and potential inconsistencies.

Quick Template

{
  description = "NixOS configuration";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
    nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-25.05";
    home-manager.url = "github:nix-community/home-manager/release-25.05";
    home-manager.inputs.nixpkgs.follows = "nixpkgs";
    # Add more inputs here
  };

  outputs = { self, nixpkgs, home-manager, ... }@inputs: {
    nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
      specialArgs = {
        inherit inputs;
        system = "x86_64-linux";
        pkgs-stable = import inputs.nixpkgs-stable {
          inherit system;
          config.allowUnfree = true;
        };
      };
      modules = [ ./hosts/myhost ];
    };
  };
}