{ description = "hyperhive deployed agents"; inputs = { hyperhive.url = "@HYPERHIVE_URL@"; nixpkgs.follows = "hyperhive/nixpkgs"; }; outputs = { self, hyperhive, ... }@inputs: let mkAgent = { name, port, archetype ? null }: let base = hyperhive.nixosConfigurations.agent-base; # Every flake an archetype can come from, by its source name. archetypeSources = { inherit hyperhive; }; agentModule = if archetype == null then inputs."agent-${name}".nixosModules.default else (archetypeSources.${archetype.source} or (throw "agent ${name}: archetype source ${archetype.source} is not an input of this hive's meta flake") ).hyperhiveArchetypes.${archetype.name}.module or (throw "agent ${name}: this hive's ${archetype.source} input has no archetype ${archetype.name}; update that input"); service = "hive-agent"; # One attrset for `environment.variables` (login shells), # `systemd.globalEnvironment` (every unit) and the harness service, # so the three cannot disagree. The forwarded vars come from the host. agentEnv = { HIVE_LABEL = name; HYPERHIVE_STATE_DIR = "/agents/${name}/state"; HYPERHIVE_HARNESS_DIR = "/agents/${name}/harness"; }; in base.extendModules { modules = [ agentModule { # The harness service inside the container runs as a # non-root unix user named after the agent (`damocles`, # `iris`, `root`, …). UID auto-assigned by NixOS; the # per-agent override here is what makes # `services.hyperhive.agent.user.name` match the agent's identity # instead of the harness default of `"agent"`. services.hyperhive.agent.user.name = name; # Without this an agent container is called `nixos` and ships # every log line under that: nixpkgs sets the hostname from the # attr name in the `containers.` submodule, and an # agent's system is its own `nixosSystem` off this flake, which # never evaluates that option. The machine name, not the # logical one — it is what `container.name` on our metrics and # nspawn itself already call this container, so logs join to # both without a prefix transform. networking.hostName = "h-${name}"; programs.git.config.user = { name = name; email = "${name}@hyperhive.local"; }; # Container-wide env, all from `agentEnv`: every unit and daemon # (the bash-task runner where `hive-forge` and `git` run included) # resolves the state dir and the forwarded service URLs without # redeclaring them. `environment.variables` is what login shells # read; `systemd.globalEnvironment` is the analogue for units. environment.variables = agentEnv; systemd.globalEnvironment = agentEnv; systemd.services.${service}.environment = agentEnv // { HIVE_PORT = toString port; }; } # Tells the harness the agent has no config repo of its own. (if archetype == null then { } else { systemd.services.${service}.environment.HIVE_ARCHETYPE = archetype.name; }) ]; }; in { nixosConfigurations = { rev1 = mkAgent { name = "rev1"; port = 8297; archetype = { source = "hyperhive"; name = "reviewer"; }; }; }; }; }