{ pkgs, lib, config, ... }: let cfg = config.services.hive-c0re; in { options.services.hive-c0re = { enable = lib.mkEnableOption "hive-c0re — hyperhive coordinator daemon"; package = lib.mkOption { type = lib.types.package; default = pkgs.hyperhive; defaultText = lib.literalExpression "pkgs.hyperhive"; description = "Package that provides /bin/hive-c0re."; }; hyperhiveFlake = lib.mkOption { type = lib.types.str; default = "/etc/hyperhive"; description = '' URL of the hyperhive flake (no fragment). Inlined into each per-agent `flake.nix` at `inputs.hyperhive.url`. The per-agent flake then pulls `hyperhive.nixosConfigurations.agent-base` to build the container. ''; }; dashboardPort = lib.mkOption { type = lib.types.port; default = 7000; description = "TCP port the hive-c0re dashboard listens on."; }; }; config = lib.mkIf cfg.enable { environment.systemPackages = [ cfg.package pkgs.git ]; # Dashboard + per-container web UIs share the host's network namespace and # need their ports reachable. Dashboard: `cfg.dashboardPort` (default 7000). # Manager: 8000. Sub-agents: 8100..8999 (deterministic hash; see # `lifecycle::agent_web_port`). networking.firewall.allowedTCPPorts = [ cfg.dashboardPort 8000 ]; networking.firewall.allowedTCPPortRanges = [ { from = 8100; to = 8999; } ]; systemd.services.hive-c0re = { description = "hyperhive coordinator daemon"; wantedBy = [ "multi-user.target" ]; path = [ "/run/current-system/sw" ]; serviceConfig = { ExecStart = "${cfg.package}/bin/hive-c0re --socket /run/hyperhive/host.sock serve --hyperhive-flake ${cfg.hyperhiveFlake} --dashboard-port ${toString cfg.dashboardPort}"; Restart = "on-failure"; RestartSec = 2; RuntimeDirectory = "hyperhive"; RuntimeDirectoryMode = "0750"; RuntimeDirectoryPreserve = "yes"; StateDirectory = "hyperhive"; }; }; }; }