{ 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"; 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: every service + co-process daemon can # resolve the agent's durable state dir without hard-coding it. # `environment.variables` only writes /etc/environment (login # shells); `systemd.globalEnvironment` is the analogue for # systemd units so forge-avatar-sync / # hive-matrix-daemon etc. can read `$HYPERHIVE_STATE_DIR` # without each service having to redeclare it. environment.variables = { HIVE_LABEL = name; HYPERHIVE_STATE_DIR = "/agents/${name}/state"; HYPERHIVE_HARNESS_DIR = "/agents/${name}/harness"; }; systemd.globalEnvironment = { HIVE_LABEL = name; HYPERHIVE_STATE_DIR = "/agents/${name}/state"; HYPERHIVE_HARNESS_DIR = "/agents/${name}/harness"; }; systemd.services.${service}.environment = { HIVE_PORT = toString port; HIVE_LABEL = name; HYPERHIVE_STATE_DIR = "/agents/${name}/state"; HYPERHIVE_HARNESS_DIR = "/agents/${name}/harness"; }; } # 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"; }; }; }; }; }