# Host Inventory Configuration

This document explains the `inventory.nix` file, which defines all hosts in your fleet.

## Table of Contents

- [Overview](#overview)
- [Structure](#structure)
- [Hostname Generation](#hostname-generation)
- [Configuration Methods](#configuration-methods)
- [Options](#options)
- [Examples](#examples)

## Overview

`inventory.nix` defines your fleet of hosts. Top-level keys are hostname **prefixes**, and actual hostnames are generated from device specifications. This allows you to manage large fleets with minimal repetition.

**Key concepts:**
- Each top-level key generates one or more NixOS configurations
- Host type defaults to the prefix name (can be overridden)
- System architecture defaults to `x86_64-linux`
- Common configuration can be applied to all devices in a group via `overrides`

## Structure

```nix
{
  "prefix-name" = {
    # Optional: Device count or explicit device map
    devices = 5;           # or { "1" = { ... }; "alpha" = { ... }; }
    
    # Optional: Hardware type (defaults to prefix name)
    type = "nix-desktop";
    
    # Optional: System architecture
    system = "x86_64-linux";
    
    # Optional: Configuration applied to ALL devices in this group
    overrides = {
      athenix.users.student.enable = true;
    };
    
    # Optional: Per-device configuration
    "device-suffix" = { ... };
  };
}
```

## Hostname Generation

Hostnames are generated automatically based on the device key:

- **Numeric keys** (`"1"`, `"2"`, `"42"`) → no dash: `prefix1`, `prefix2`, `prefix42`
- **Non-numeric keys** (`"alpha"`, `"special"`) → with dash: `prefix-alpha`, `prefix-special`
- **Custom hostnames** → Set `athenix.host.useHostPrefix = false` to use the suffix as the full hostname (no prefix)

**Examples:**

```nix
nix-laptop = {
  devices = 3;  # Generates: nix-laptop1, nix-laptop2, nix-laptop3
};

nix-surface = {
  devices = {
    "1" = { };  # → nix-surface1
    "special" = { };  # → nix-surface-special
  };
};

custom-machine = {
  devices."lab-machine" = {
    athenix.host.useHostPrefix = false;  # → lab-machine (not custom-machine-lab-machine)
  };
};
```

## Configuration Methods

### Method 1: Simple Count

Create N identical hosts:

```nix
nix-laptop = {
  devices = 5;
};
# Generates: nix-laptop1, nix-laptop2, nix-laptop3, nix-laptop4, nix-laptop5
```

### Method 2: Simple Count with Overrides

Create N hosts with common configuration:

```nix
nix-desktop = {
  devices = 3;
  overrides = {
    athenix.users.student.enable = true;
    athenix.sw.extraPackages = with pkgs; [ vim git ];
    services.openssh.enable = true;
  };
};
# All three hosts get the overrides configuration
```

### Method 3: Explicit Device Map

Configure each device individually:

```nix
nix-surface = {
  devices = {
    "1".athenix.sw.kioskUrl = "https://dashboard1.example.com";
    "2".athenix.sw.kioskUrl = "https://dashboard2.example.com";
    "3" = {
      athenix.sw.kioskUrl = "https://dashboard3.example.com";
      services.openssh.enable = false;
    };
  };
};
```

### Method 4: External Module

Reference a Git repository using the `external` field (lazy evaluation):

```nix
nix-lxc = {
  devices."builder".external = builtins.fetchGit {
    url = "https://git.factory.uga.edu/org/builder-config";
    rev = "abc123...";
  };
};
```

### Method 5: Mixed Approach

Combine default count, custom devices, and overrides:

```nix
nix-lab = {
  defaultCount = 5;  # Creates nix-lab1 through nix-lab5
  devices = {
    "special" = {
      athenix.sw.extraPackages = with pkgs; [ special-software ];
    };
  };
  overrides = {
    # Applied to all devices (default count + custom)
    athenix.users.lab-admin.enable = true;
  };
};
```

## Options

### Top-Level Device Options

#### `devices`

Specify hosts to create. Can be:
- **Number**: Create N hosts with keys `"1"`, `"2"`, ..., `"N"`
- **Attribute set**: Map of device names to configurations

**Type**: `int | attrs`

**Examples:**
```nix
devices = 5;  # Creates 5 hosts

devices = {
  "1" = { };
  "alpha" = { };
};
```

#### `defaultCount`

When using a device map, also create N numbered hosts.

**Type**: `int` (optional)

**Example:**
```nix
defaultCount = 3;  # Creates "1", "2", "3" in addition to devices map
devices = {
  "special" = { };
};
# Result: hosts "1", "2", "3", and "special"
```

#### `type`

Hardware type module to use. Defaults to the prefix name (inferred from top-level key).

**Type**: `string` (optional)

**Options**: `nix-desktop`, `nix-laptop`, `nix-surface`, `nix-lxc`, `nix-wsl`, `nix-ephemeral`

**Example:**
```nix
lab-machines = {
  type = "nix-desktop";  # Use desktop hardware configuration
  devices = 5;
};
```

#### `system`

System architecture. Defaults to `x86_64-linux`.

**Type**: `string` (optional)

**Example:**
```nix
arm-devices = {
  system = "aarch64-linux";
  devices = 2;
};
```

#### `overrides`

Configuration applied to all devices in this group. Useful for fleet-wide settings.

**Type**: `attrs` (optional)

**Example:**
```nix
nix-laptop = {
  devices = 10;
  overrides = {
    # Applied to all 10 laptops
    athenix.users.staff.enable = true;
    services.openssh.enable = true;
    boot.loader.timeout = 10;
  };
};
```

### Per-Device Options

Any NixOS or `athenix.*` option can be set per-device:

```nix
nix-surface = {
  devices = {
    "1" = {
      # athenix.* namespace options
      athenix.users.student.enable = true;
      athenix.host.filesystem.device = "/dev/sda";
      athenix.host.filesystem.swapSize = "16G";
      athenix.sw.kioskUrl = "https://dashboard1.example.com";
      athenix.sw.extraPackages = with pkgs; [ firefox ];
      
      # Standard NixOS options
      networking.firewall.enable = false;
      services.openssh.enable = true;
      time.timeZone = "America/New_York";
      boot.kernelPackages = pkgs.linuxPackages_latest;
    };
  };
};
```

### Convenience: `athenix.forUser`

Quick setup for single-user systems (especially WSL). This automatically enables a user and sets the WSL default user:

```nix
nix-wsl = {
  devices = {
    "alice".athenix.forUser = "alice-username";
  };
};
```

This automatically enables the user account.

### External System Configuration

For complex configurations, use external modules (see [EXTERNAL_MODULES.md](../EXTERNAL_MODULES.md)):

```nix
nix-lxc = {
  devices = {
    "special-server" = builtins.fetchGit {
      url = "https://git.factory.uga.edu/org/server-config";
      rev = "abc123...";
    };
  };
};
```

## Examples

### Simple Lab Computers

```nix
nix-laptop = {
  devices = 10;  # Creates nix-laptop1 through nix-laptop10
  overrides = {
    athenix.users.student.enable = true;
  };
};
```

### Mixed Surface Tablets

```nix
nix-surface = {
  defaultCount = 5;  # nix-surface1 through nix-surface5 (default config)
  devices = {
    "admin" = {  # nix-surface-admin (special config)
      athenix.sw.type = "desktop";  # Full desktop instead of kiosk
      athenix.users.admin.enable = true;
    };
  };
  overrides = {
    athenix.sw.type = "tablet-kiosk";
    athenix.sw.kioskUrl = "https://dashboard.factory.uga.edu";
  };
};
```

### LXC Containers

```nix
nix-lxc = {
  devices = {
    "nix-builder" = {
      athenix.sw.type = "headless";
    };
    "webserver" = {
      athenix.sw.type = "headless";
      services.nginx.enable = true;
    };
  };
  overrides = {
    athenix.host.useHostPrefix = false;  # Use exact device key as hostname
  };
};
```

### WSL Instances

```nix
nix-wsl = {
  devices = {
    "alice".athenix.forUser = "alice-uga";
    "bob".athenix.forUser = "bob-uga";
  };
};
```

## See Also

- [USER_CONFIGURATION.md](USER_CONFIGURATION.md) - User account management
- [EXTERNAL_MODULES.md](EXTERNAL_MODULES.md) - External configuration modules
- [Configuration Namespace Reference](NAMESPACE.md) - All `athenix.*` options
