# Rigging Multi-repo NixOS + Nomad infrastructure management CLI and flake-parts module. ## What this is Three components: 1. **Flake-parts module** (`flake-module.nix`) — repos import this to declare what they provide and expose a `bosun-manifest` package (JSON derivation) 2. **Nushell CLI** (`cli/rigging.nu`) — reads `~/.config/bosun/config.toml`, builds each repo's manifest via `nix build`, aggregates, dispatches commands 3. **Bash CLI** (`cli/default.nix`) — repo-local Nomad job operations with runtime variable support ## File layout ``` flake.nix # exports flakeModules.default + lib flake-module.nix # the flake-parts module (top-level bosun.{meta,hosts} + perSystem bosun.{enable,jobsDir,...}) cli/ default.nix # bash bosun CLI (repo-local Nomad ops) rigging.nix # nix wrapper for the nushell CLI rigging.nu # nushell CLI source lib/ default.nix # bosun library (discoverJobs, evalJob, compileJobs, etc.) nomad.nix # nomad helpers (traefikTags, pinToHost, resources, etc.) nushell.nix # writeNushellApplication (bundled, no overlay needed) ``` ## How consumers use it Consumers add this as a flake input and import `flakeModules.default`. This gives them: - `bosun.meta.name` / `bosun.hosts` — top-level options for repo identity + host declarations - `perSystem.bosun.{enable,jobsDir,nomadAddress,...}` — Nomad job management - `packages.bosun-manifest` — always generated JSON manifest - `packages.rigging` — the multi-repo CLI - `packages.bosun` — repo-local Nomad CLI (only when `bosun.enable = true`) The manifest is the key integration point: `rigging` builds each repo's manifest via `nix build #bosun-manifest`, reads the JSON, and knows what hosts/jobs each repo provides. ## Key design decisions - **No legacyPackages for vars**: Runtime job evaluation with variables uses `nix eval --expr` inline (same pattern as the bash CLI). The `legacyPackages.bosun.evalJobWithVars` exists for backward compat but the CLI constructs the eval expression directly. - **Rigging delegates Nomad ops**: The nushell CLI is a thin orchestration layer. For actual Nomad operations (run, plan, stop, etc.), it delegates to the repo-local bash CLI via `nix run #bosun -- `. - **writeNushellApplication bundled**: `lib/nushell.nix` is a self-contained copy so consumers don't need an overlay. - **Top-level + perSystem split**: `bosun.meta`/`bosun.hosts` are flake-level options (shared across systems). Nomad job config is perSystem (needs `pkgs`). The manifest bridges both by reading top-level config from within perSystem via closure over `topArgs.config.bosun`. - **`mkMerge`/`mkIf` for config**: The perSystem config uses `mkMerge` + `mkIf` (not `//` + `lib.optionalAttrs`) to avoid infinite recursion when the module system evaluates packages. ## Vision The end state: `rigging` is installed globally (via home-manager or devShell) and manages all infrastructure repos. Each repo is self-describing — `rigging repo add ` discovers everything. Commands like `rigging host deploy alvin` or `rigging job run forgejo` Just Work regardless of which repo owns the resource. Phase 4 (pending): wire up dotfiles repo as a second consumer. Phase 5: drop the bash CLI once rigging fully replaces it.