{ 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. ''; }; }; config = lib.mkIf cfg.enable { environment.systemPackages = [ cfg.package ]; # Per-container web UIs share the host's network namespace and need their # ports reachable. Manager: 8000. Sub-agents: 8100..8999 (deterministic # hash; see `lifecycle::agent_web_port`). networking.firewall.allowedTCPPorts = [ 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}"; Restart = "on-failure"; RestartSec = 2; RuntimeDirectory = "hyperhive"; RuntimeDirectoryMode = "0750"; RuntimeDirectoryPreserve = "yes"; StateDirectory = "hyperhive"; }; }; }; }