hyperhive — host options

services.hyperhive.enable

Whether to enable hyperhive — the agent swarm coordinator.

Type: boolean

Default:

false

Example:

true

Declared by:

services.hyperhive.c0re.enable

Enable hive-c0re coordinator daemon (auto-enabled by services.hyperhive.enable).

Type: boolean

Default:

config.services.hyperhive.enable

Declared by:

services.hyperhive.c0re.package

hyperhive workspace package. Provides /bin/hive-c0re (coordinator daemon) and /bin/hivectl (operator-facing host CLI for ad-hoc administration + the host admin socket). Wired to this flake’s packages.<system>.default by nixosModules.default (via lib.mkDefault, so setting it here wins).

Type: package

Default:

hyperhive.packages.${system}.default

Declared by:

services.hyperhive.c0re.adminUsers

Login users granted sudoless hivectl. Each is added to the hive-admin group, which group-owns the host admin socket (/run/hyperhive/host.sock, mode 0660) — so listed users drive hivectl (and thus the whole hive) without sudo.

This is a real privilege grant: the admin socket is full hive control — spawn / kill / destroy / deploy — see docs/boundary.md. Keep the list to trusted operators. Empty (the default) keeps the socket root-only, as before.

Type: list of string

Default:

[ ]

Example:

[
  "alice"
]

Declared by:

services.hyperhive.c0re.agentBaseToplevel

Pre-built agent-base container system closure, pulled into the host system closure when preBuildAgentTemplates is on. Wired by nixosModules.default; only evaluated when that option is enabled.

Type: package

Default:

hyperhive.packages.x86_64-linux.agent-base-toplevel

Declared by:

services.hyperhive.c0re.agentCpuQuota

systemd CPUQuota= applied to every agent container via a container@h-<name>.service.d/ drop-in written on each spawn/rebuild. Expressed as a percentage of one CPU core — "200%" allows each agent to use up to 2 cores. Bump this if agents are hitting CPU limits during builds or heavy tool use.

For a hive-wide cap across all containers, set systemd.slices.machine.serviceConfig.CPUQuota in your NixOS config (all nspawn containers live in machine.slice).

Type: string

Default:

"200%"

Example:

"400%"

Declared by:

services.hyperhive.c0re.agentMemoryMax

systemd MemoryMax= applied to every agent container via the same drop-in as agentCpuQuota.

Type: string

Default:

"4G"

Example:

"8G"

Declared by:

services.hyperhive.c0re.assets

Bundled static runtime assets (see nix/packages/assets.nix): the project’s branding family + the claude system-prompt template + claude-settings JSON. Output has share/hyperhive/{branding,prompts}/; passed to hive-c0re’s systemd unit via HIVE_ASSETS_DIR (hive_sh4re::assets::* resolve paths underneath). Override to ship customised branding or prompts without rebuilding the rust derivation.

Type: package

Default:

hyperhive.packages.${system}.assets

Declared by:

services.hyperhive.c0re.buildSlots

Number of nix-heavy job-queue nodes (container prebuilds, profile swaps, first-spawn creates, meta lock bumps) hive-c0re runs concurrently. The default of 1 serializes all heavy nix work; raise it on hosts with the cores/RAM to build several agent toplevels at once. Per-agent correctness is independent of this count — each agent’s container-affecting operations are serialized by its lifecycle lease regardless.

Type: positive integer, meaning >0

Default:

1

Example:

2

Declared by:

services.hyperhive.c0re.contextWindowTokens

Per-model context-window sizes in tokens. Each key is a model-family short name matched case-insensitively as a substring of the active model name at runtime (e.g. "sonnet" matches "claude-sonnet-4-5"). The defaults cover the known Anthropic families; add entries for new models or override existing ones here to change the window for all agents at once.

Passed to hive-c0re serve as JSON and injected into every container’s harness service environment as HIVE_CONTEXT_WINDOW_TOKENS_<KEY_UPPER>. Changes propagate on the next ↻ R3BU1LD — no per-agent approval needed.

Type: attribute set of signed integer

Default:

{
  haiku = 200000;
  opus = 1000000;
  sonnet = 1000000;
}

Example:

{
  haiku = 150000;
  sonnet = 900000;
}

Declared by:

services.hyperhive.c0re.dashboardPort

TCP port the hive-c0re dashboard listens on.

Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)

Default:

7000

Declared by:

services.hyperhive.c0re.frontend

Bundled frontend dist (see nix/packages/frontend.nix). Output has dashboard/ and agent/ subdirectories — hive-c0re serves dashboard/ via tower_http::ServeDir from the path passed in HIVE_STATIC_DIR. Override to ship a custom dashboard SPA; the JSON contract (/api/state, the SSE streams, the action endpoints) is the source of truth for any replacement.

Type: package

Default:

hyperhive.packages.${system}.frontend

Declared by:

services.hyperhive.c0re.hyperhiveDocs

URL of the narrow docs/ source (no fragment). Inlined into the generated meta flake.nix at inputs.hyperhive-docs.url and threaded to each agent as hyperhive.docs.source, from which the harness resolves $HIVE_DOCS_DIR. Its own store path — separate from hyperhiveFlake — so a doc edit only re-locks this input instead of rebuilding every agent container.

Type: string

Default: the docs/ tree’s own store path

Declared by:

services.hyperhive.c0re.hyperhiveFlake

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. Wired by nixosModules.default to this flake’s own filtered source — only override if you want agents tracking a different ref.

Type: string

Default: the hyperhive flake’s own filtered source store path

Declared by:

services.hyperhive.c0re.managerToplevel

Pre-built manager (ruth) container system closure — see agentBaseToplevel.

Type: package

Default:

hyperhive.packages.x86_64-linux.ruth-toplevel

Declared by:

services.hyperhive.c0re.modelPrices

Per-model USD prices (per million tokens) used for the hive-wide cost estimate on the dashboard’s ST4TS tab. Each key is a model-family short name matched case-insensitively as a substring of the active model id at runtime (e.g. "sonnet" matches "claude-sonnet-4-5"); the longest matching key wins, so a specific entry beats a generic family name. Any model not covered by this table falls back to hive-c0re’s built-in estimate.

The defaults track Anthropic list pricing at the time of writing — override them here to keep the estimate current without a code change. Passed to hive-c0re serve as JSON via --model-prices; read only by hive-c0re itself (not injected into containers). Changes apply on the next host rebuild.

Type: attribute set of (submodule)

Default:

{
  haiku = {
    cache_read = 0.1;
    cache_write = 2.0;
    input = 1.0;
    output = 5.0;
  };
  opus = {
    cache_read = 0.5;
    cache_write = 10.0;
    input = 5.0;
    output = 25.0;
  };
  sonnet = {
    cache_read = 0.3;
    cache_write = 6.0;
    input = 3.0;
    output = 15.0;
  };
}

Example:

{
  sonnet = {
    cache_read = 0.3;
    cache_write = 6.0;
    input = 3.0;
    output = 15.0;
  };
}

Declared by:

services.hyperhive.c0re.modelPrices.<name>.cache_read

USD per million cache-read tokens.

Type: nonnegative integer or floating point number, meaning >=0

Declared by:

services.hyperhive.c0re.modelPrices.<name>.cache_write

USD per million cache-creation (write) tokens.

Type: nonnegative integer or floating point number, meaning >=0

Declared by:

services.hyperhive.c0re.modelPrices.<name>.input

USD per million input tokens.

Type: nonnegative integer or floating point number, meaning >=0

Declared by:

services.hyperhive.c0re.modelPrices.<name>.output

USD per million output tokens.

Type: nonnegative integer or floating point number, meaning >=0

Declared by:

services.hyperhive.c0re.nixpkgsFlake

Store-path URL for the nixpkgs input in the generated meta flake. The meta flake declares this as a top-level input and wires inputs.hyperhive.inputs.nixpkgs.follows = "nixpkgs" so every agent container evaluates with this exact nixpkgs.

Defaults to "path:${pkgs.path}" — the store path of the nixpkgs the host NixOS module was evaluated with. When the operator sets inputs.hyperhive.inputs.nixpkgs.follows = "nixpkgs" in their host flake, pkgs.path resolves to the host’s own nixpkgs, so agents transparently track the same channel as the host.

Override to pin agents to a specific nixpkgs version regardless of the host’s channel.

Type: string

Default: "path:${pkgs.path}"

Declared by:

services.hyperhive.c0re.operatorPronouns

Operator pronouns, free text. Threaded into every agent container as the HIVE_OPERATOR_PRONOUNS env var; the harness substitutes it into the agent / manager system prompt at boot so claude refers to the operator naturally in third person (“ask her”, “tell them”, etc.). Changes propagate to running agents on the next ↻ R3BU1LD — forwards as a meta flake env-var bump, no per-agent approval needed.

Type: string

Default:

"she/her"

Example:

"they/them"

Declared by:

services.hyperhive.c0re.preBuildAgentTemplates

Pre-fetch the per-container system closures (agent-base + manager toplevels) into the host’s /nix/store as part of this host’s NixOS build, instead of letting the first agent spawn do all the work.

Enabling this adds roughly the full nixpkgs runtime closure + claude-code + the harness binary to your system closure size (low single-digit GB), but the first nixos-container start for any agent then completes in seconds instead of minutes because nothing’s left to fetch.

Off by default because the toplevels are pinned to x86_64-linux (nixos-containers run native arch). Enabling on an aarch64 host would force nix to build the x86 closure via cross or a remote builder, which is rarely what you want. Flip to true on an x86_64 host when you care more about first-spawn latency than host store size — or just nix build .#agent-base-toplevel once manually to warm the store.

Type: boolean

Default:

false

Example:

true

Declared by:

services.hyperhive.c0re.xdgIcons

XDG icon set + .desktop entries for hyperhive processes (see nix/packages/hive-xdg-icons.nix), installed into the host system packages so desktop environments can match hyperhive processes to their icon.

Type: package

Default:

hyperhive.packages.${system}.xdg-icons

Declared by:

services.hyperhive.domain

Canonical host domain for hyperhive subsystems that need a stable name (currently: services.hyperhive.matrix.serverName derives from this, defaulting to matrix.${services.hyperhive.domain} when serverName is null). Required when services.hyperhive.enable — eval fails with a helpful message if it’s unset (it’s baked into matrix on first boot and drives the gateway/forge/agent URLs, with no safe default; changing it later is destructive). Exposed to agents as HYPERHIVE_HIVE_DOMAIN; consumed by hive-agent::identity::hive_domain() for <name>@<domain> qualified labels.

Type: null or string

Default:

null

Example:

"darkest.space"

Declared by:

services.hyperhive.forge.package

Forgejo package to run inside the container. Defaults to pkgs.forgejo (the latest release line) rather than the nixpkgs-module default of pkgs.forgejo-lts, because LTS lags far behind on schema and the DB easily ends up “newer than the binary” if the operator ever ran a non-LTS forgejo against the same state dir. Override to pkgs.forgejo-lts if you actively want the slower release train.

Type: package

Default:

pkgs.forgejo

Declared by:

services.hyperhive.forge.behindGateway

Serve forgejo through the hive-gateway nginx as a sub-domain vhost (server_name = cfg.domain) instead of directly on httpPort (sub-domain routing — see docs/gateway.md).

When true:

Defaults to services.hyperhive.enable (the gateway always runs alongside hyperhive, so forge auto-routes through it). Set false explicitly to keep forge on the direct port even though the gateway is running (e.g. an external git client that doesn’t traverse the gateway).

Sub-domain routing is the preferred shape for forge + matrix (both are external standard apps with sub-domain-native config defaults). Per-agent UIs stay on sub-path (/agent/<name>/) because they’re hyperhive-internal + already base-path-aware.

Type: boolean

Default:

config.services.hyperhive.enable

Declared by:

services.hyperhive.forge.ci.enable

Run a Forgejo Actions runner in a hive-ci nixos-container. Grouped under services.hyperhive.forge because the runner is tightly coupled to the forge instance it registers against. Disabled by default; the internal forge it registers against is always present (mandatory), so enabling this is all that’s needed.

On first start the container auto-registers against hive-forge using hive-c0re’s admin token — no manual token provisioning needed. Runner credentials are persisted in the container’s state dir and reused on every subsequent boot.

Type: boolean

Default:

false

Example:

true

Declared by:

services.hyperhive.forge.ci.package

gitea-actions-runner package.

Type: package

Default:

pkgs.gitea-actions-runner

Declared by:

services.hyperhive.forge.ci.concurrency

Maximum number of workflow jobs the runner executes in parallel. Each job gets its own temporary working directory; multiple parallel jobs share the container’s nix store and cargo registry cache. Higher values trade memory + CPU headroom for throughput.

Type: positive integer, meaning >0

Default:

1

Example:

4

Declared by:

services.hyperhive.forge.ci.jobTimeout

Per-job wall-clock timeout the runner enforces (act_runner’s runner.timeout). A job that exceeds it is killed, so a hung or runaway build is bounded instead of holding the runner’s single slot indefinitely. Default 1h comfortably covers a cold-cache nix build while still bounding a stuck job; raise it (e.g. "3h") if you legitimately run jobs longer than that. Accepts a Go duration string (30m, 1h, 2h30m). Note: this is enforced by the runner process, so it only fires while that process is itself healthy.

Type: string

Default:

"1h"

Example:

"3h"

Declared by:

services.hyperhive.forge.ci.labels

Runner labels in <name>:<scheme> format. The host scheme runs commands directly in the container (no docker/podman). Workflow files target this runner with runs-on: [hive-ci].

Type: list of string

Default:

[
  "hive-ci:host"
]

Example:

[
  "hive-ci:host"
  "nix:host"
]

Declared by:

services.hyperhive.forge.ci.name

Runner name as shown in the Forgejo admin panel. Defaults to “hive-ci”; override when multiple hives share a Forgejo instance.

Type: string

Default:

"hive-ci"

Example:

"prod-hive"

Declared by:

services.hyperhive.forge.domain

Public hostname for the forge. Doubles as both the forgejo DOMAIN setting (clone URLs forgejo advertises) AND the gateway vhost server-name when behindGateway = true (sub-domain routing — see docs/gateway.md).

Defaults to forge.${services.hyperhive.domain} (idiomatic sub-domain shape — forge labelled under the hive’s bare domain). services.hyperhive.domain is required, so there’s always a domain to derive from.

Set to a full hostname (git.example.com, forge.internal.lan, etc.) for a bespoke vhost shape — the full domain goes here, no separate sub-domain-label option.

Type: string

Default:

"forge.${services.hyperhive.domain}"

Example:

"git.example.com"

Declared by:

services.hyperhive.forge.httpPort

TCP port the forge serves HTTP on. Default 3000 sits outside hyperhive’s claimed ranges (dashboard 7000, every agent in 8100…8999 via FNV-1a hash). Change this if you already have another forgejo bound to 3000.

Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)

Default:

3000

Declared by:

services.hyperhive.forge.mirrors

General-purpose Forgejo pull-mirrors to auto-seed on the local forge. Each entry is created as a real Forgejo pull-mirror (it re-syncs from upstream out-of-band), not a one-off pushed clone — so a host-resolver blip leaves a stale mirror, never a hard failure on whatever reads it.

When services.hyperhive.forge.ci.enable is set, an actions/checkout mirror is auto-appended to this list and forgejo’s DEFAULT_ACTIONS_URL is pointed at this instance, so CI uses: actions/checkout@vN steps resolve entirely on loopback with no external DNS on the critical path (the seed/re-sync needs external DNS, but that’s off the CI path).

Type: list of (submodule)

Default:

[ ]

Example:

[ { upstream = "https://github.com/actions/checkout"; dest = "actions/checkout"; } ]

Declared by:

services.hyperhive.forge.mirrors.*.dest

Local <owner>/<repo> the pull-mirror is created at. The <owner> org is auto-created if missing. Keep mirror dests in their own orgs (e.g. actions/*) — separate from the hive-c0re-managed namespaces (config/shared/agents/core) so the seed never collides with core’s own provisioning.

Type: string

Example:

"actions/checkout"

Declared by:

services.hyperhive.forge.mirrors.*.upstream

Upstream clone URL to mirror from.

Type: string

Example:

"https://github.com/actions/checkout"

Declared by:

services.hyperhive.forge.openFirewall

Open httpPort + sshPort in the host firewall. Off by default (secure-by-default): agent containers reach the forge at forge.<domain> via the gateway (not directly), and the host reaches it on loopback — so the firewall opens only matter for access from outside the host. Flip to true when you want the operator’s browser or external git clients to hit the forge directly.

Breaking change: this used to default to true. If you relied on the old default for external reach, add services.hyperhive.forge.openFirewall = true; to your host config before rebuilding.

Type: boolean

Default:

false

Example:

true

Declared by:

services.hyperhive.forge.rootUrl

Override the auto-derived forgejo ROOT_URL. When null (default), ROOT_URL is derived from cfg.domain + gateway state, including the scheme:

The TLS scheme is derived automatically now, so you only need to set this for a genuinely bespoke shape (e.g. an external reverse proxy on a different host/path). Must end with / per forgejo’s ROOT_URL contract.

Type: null or string

Default:

null

Example:

"https://forge.example.com/"

Declared by:

services.hyperhive.forge.sshPort

TCP port the forge’s built-in SSH server listens on. Kept off 22 so it doesn’t clash with the host’s openssh. Agents push with ssh -p <sshPort> git@<domain>:<owner>/<repo>.git.

Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)

Default:

2222

Declared by:

services.hyperhive.gateway.auth.enable

Whether to enable HTTP basic auth on the gateway using an htpasswd file. When enabled, every request to the gateway’s main vhost requires a valid username and password. nginx’s built-in auth_basic module validates credentials against /var/lib/hyperhive/gateway/gateway.htpasswd on the host (exposed as /run/hive-state/gateway.htpasswd inside the container via the existing gateway state bind-mount). Off by default.

Manage users with hivectl gateway create-user, delete-user, and list-users — see hivectl gateway --help for usage. The htpasswd file is created automatically when auth is enabled; add at least one user before enabling to avoid locking everyone out. .

Type: boolean

Default:

false

Example:

true

Declared by:

services.hyperhive.gateway.auth.realm

HTTP Basic auth realm value sent in the WWW-Authenticate header when credentials are absent or rejected. Must not contain " or $ (nginx string metacharacters).

Type: string matching the pattern [^"$]*

Default:

"hyperhive"

Example:

"my-hive"

Declared by:

services.hyperhive.gateway.hsts.enable

Add Strict-Transport-Security to all gateway vhosts.

Disabled by default: HSTS pins HTTPS in the browser’s HSTS preload list; enabling it on a deployment that later loses TLS will lock browsers out until the max-age expires. Only enable this when you are certain TLS is permanent.

The gateway always terminates TLS (self-signed floor), so HSTS is always served over https when enabled — but mind the warning above: HSTS pins https in the browser, so only enable it when TLS is permanent for this deployment.

Type: boolean

Default:

false

Declared by:

services.hyperhive.gateway.hsts.includeSubDomains

Whether to include includeSubDomains in the HSTS header. Only disable this if the gateway host has sub-domains that intentionally serve plain HTTP.

Type: boolean

Default:

true

Declared by:

services.hyperhive.gateway.hsts.maxAge

Value for the max-age directive in seconds. Default: 31536000 (1 year), which is the value required for HSTS preload list submission. Use a shorter value (e.g. 86400) while testing so browsers forget the pin quickly.

Type: positive integer, meaning >0

Default:

31536000

Example:

86400

Declared by:

services.hyperhive.gateway.httpsPort

TCP port for the TLS-terminated vhosts. Default 443. The gateway always terminates TLS (self-signed is the implicit floor when no tls.certDir / ACME is configured), so this port is always active alongside the plain-http port.

Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)

Default:

443

Example:

8443

Declared by:

services.hyperhive.gateway.localHostsEntry

Add an /etc/hosts entry mapping services.hyperhive.domain to 127.0.0.1 on the host. Useful for local deployments + tests where there’s no real DNS for services.hyperhive.domain but the operator (or browser-based tests) want to hit http://${services.hyperhive.domain} to exercise the gateway shape. Off by default — operators running with real DNS shouldn’t have a stale /etc/hosts entry sticking around. Requires services.hyperhive.domain to be set.

Type: boolean

Default:

false

Example:

true

Declared by:

services.hyperhive.gateway.openFirewall

Open port in the host firewall. Off by default (secure-by-default). Flip to true to expose the gateway to the operator’s browser / external clients — required for any out-of-host reach, since the agents themselves talk to hive-c0re via the per-agent unix sockets and don’t need the nginx vhost. Leave off when running behind another reverse proxy (e.g. caddy / traefik on the host) that handles TLS termination + forwards to port.

Note: this used to default to true. Add services.hyperhive.gateway.openFirewall = true; to your host config if external reach stopped working after a recent upgrade.

Type: boolean

Default:

false

Example:

true

Declared by:

services.hyperhive.gateway.port

TCP port the gateway listens on. Default 80 (canonical web port). nginx inside the container binds <1024 because the container’s init runs as root; if 80 is already taken on the host (existing nginx, traefik, etc.) override to an unused port like 8080 or move the conflicting service.

Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)

Default:

80

Example:

8080

Declared by:

services.hyperhive.gateway.tls.acme.enable

Let nginx inside the gateway container obtain and renew TLS certificates automatically via ACME (Let’s Encrypt). When enabled, each vhost calls out to Let’s Encrypt using the HTTP-01 challenge on port (default 80) and stores certs inside the gateway container’s persistent state dir.

Requirements:

Mutual exclusion: tls.certDir set together with tls.acme.enable = true fails at eval — pick one TLS source.

Typical setup:

services.hyperhive.gateway = {
  openFirewall  = true;
  tls.acme = {
    enable = true;
    email  = "admin@example.com";
  };
};

After enabling, peer hives can omit certFingerprint in swarm.peers — Let’s Encrypt certs are CA-trusted by default.

Type: boolean

Default:

false

Example:

true

Declared by:

services.hyperhive.gateway.tls.acme.email

Email address for the ACME account registration with Let’s Encrypt. Required when tls.acme.enable = true. Let’s Encrypt sends expiry warnings to this address.

Type: null or string

Default:

null

Example:

"admin@example.com"

Declared by:

services.hyperhive.gateway.tls.certDir

Path to a host directory containing a TLS certificate and private key for nginx. When set, nginx listens on httpsPort and uses this cert, overriding the self-signed default — the auto-generated hive-CA-signed leaf is skipped entirely.

The directory is bind-mounted read-only into the gateway container at /run/hive-tls/. nginx reads <certDir>/<tls.certName> and <certDir>/<tls.keyName>. Default filenames (cert.pem / key.pem) match the output layout of nixpkgs’s security.acme module.

Typical ACME setup:

security.acme.certs."example.com" = { ... };
services.hyperhive.gateway.tls.certDir =
  config.security.acme.certs."example.com".directory;

When using an external CA cert, peer hives can declare this hive in services.hyperhive.swarm.peers without certFingerprint — the standard CA bundle validates.

Mutual exclusion with tls.acme.enable — set one or the other, not both.

Type: null or absolute path

Default:

null

Example:

"/var/lib/acme/example.com"

Declared by:

services.hyperhive.gateway.tls.certName

Filename of the TLS certificate within tls.certDir. Defaults to cert.pem which matches nixpkgs’s security.acme output.

Type: string

Default:

"cert.pem"

Declared by:

services.hyperhive.gateway.tls.keyName

Filename of the TLS private key within tls.certDir. Defaults to key.pem which matches nixpkgs’s security.acme output.

Type: string

Default:

"key.pem"

Declared by:

services.hyperhive.gateway.upstreamHost

Host the gateway proxies non-static requests to. Defaults to 127.0.0.1 because the gateway container shares the host netns, so loopback resolves directly to hive-c0re.

Type: string

Default:

"127.0.0.1"

Declared by:

services.hyperhive.gateway.upstreamPort

TCP port the gateway proxies non-static requests to. Defaults to 7000 (hive-c0re’s out-of-the-box dashboard port). Operators who change services.hyperhive.c0re.dashboardPort should set upstreamPort to match — kept as a hardcoded default rather than a cross-reference to keep this module’s options eval independent of c0re’s option tree shape.

Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)

Default:

7000

Declared by:

services.hyperhive.github.enable

Hive-wide switch for the per-agent GitHub integration (the gh CLI wrapper + git credential helper, per hyperhive.github.enable). On by default: every agent gets the integration, inert until a PAT is provisioned via the dashboard credentials tab or hivectl github set-token. Set false to turn it off for the whole hive — the meta-flake renderer (hive-c0re/src/meta.rs) then injects hyperhive.github.enable = false into every agent. Exposed to hive-c0re as HYPERHIVE_GITHUB_DISABLED (set only when the integration is off).

Type: boolean

Default:

true

Example:

false

Declared by:

services.hyperhive.hiveName

Human-readable name of this single-host hive instance. Distinct from services.hyperhive.domain (the machine- addressable DNS name): the domain may carry the hive name as its leftmost label by convention, but this option is the canonical readable identity. Exposed to agents as HYPERHIVE_HIVE_NAME; surfaced in the dashboard chrome and per-agent system prompt when set. Null falls back to the default behaviour (chrome shows the domain, prompt doesn’t mention a hive name).

Type: null or string

Default:

null

Example:

"pr1ma"

Declared by:

services.hyperhive.matrix.enable

Run hive-matrix — a private matrix-tuwunel homeserver (in a nixos-container) for hyperhive agents. Off by default while the integration phases in; flip to true once the operator has set services.hyperhive.domain and is ready to onboard agents.

Type: boolean

Default:

false

Declared by:

services.hyperhive.matrix.package

matrix-tuwunel package to run inside the container. Defaults to nixpkgs’s pkgs.matrix-tuwunel. Override to pin a specific upstream if you need an unreleased feature.

Type: package

Default:

pkgs.matrix-tuwunel

Declared by:

services.hyperhive.matrix.allowEncryption

Server-side switch for matrix end-to-end encryption — sets tuwunel’s allow_encryption. Off by default: on the hive-internal homeserver the operator already controls the transport, so server E2EE adds key-management overhead (cross-signing, device verification, undecryptable-message recovery) without a clear threat-model win for the common single-hive case. Turn on when agents join encrypted rooms on external / federated homeservers, or when the operator wants message contents opaque to the homeserver admin. Independent of the agent matrix client, which always supports decryption so it can read encrypted rooms it is invited to regardless of this flag; this option only governs whether THIS homeserver permits room encryption.

Type: boolean

Default:

false

Declared by:

services.hyperhive.matrix.gatewayHost

Public hostname for the matrix homeserver behind the gateway. Defaults to matrix.${services.hyperhive.domain} (sub-domain shape — see docs/gateway.md). Set to null to skip the gateway vhost (tuwunel stays direct on httpPort). See docs/gateway.md for the vhost map + matrix discovery flow, and the federation port-8448 caveat at the bottom of that doc.

Note: gatewayHost is the API listener hostname (where nginx proxies /_matrix/*); serverName is the matrix-identifier domain embedded irrevocably in user/room IDs (default = bare hive-domain). The two are distinct.

Type: null or string

Default:

"matrix.${services.hyperhive.domain}"

Example:

"matrix.example.com"

Declared by:

services.hyperhive.matrix.gui.enable

Serve a matrix web client at matrix.${services.hyperhive.domain}/. Requires matrix.gatewayHost != null (default matrix.<hive> when hive-domain set); the gateway itself always runs. When off, the dashboard’s M4TR1X → tab is hidden. See docs/gateway.md for the discovery flow that lets clients auto-find the sub-domain.

Type: boolean

Default:

config.services.hyperhive.matrix.enable

Declared by:

services.hyperhive.matrix.gui.package

Static web client dist served at matrix.<hive>/. Override to swap fluffychat for hydrogen-web, cinny, element-web, or an out-of-tree dist — any replacement is mounted at the sub-domain root with the upstream-default <base href "/">, no sub-path gymnastics needed.

Type: package

Default: pkgs.fluffychat-web with a postInstall patch that adds the three files flutter341.buildFlutterApplication skips.

Declared by:

services.hyperhive.matrix.httpPort

TCP port tuwunel serves the matrix client-server API on. Default 8008 is the matrix-spec well-known port. Sits outside hyperhive’s claimed ranges (dashboard 7000, every agent in 8100…8999 via FNV-1a hash). Federation listens on federationPort separately.

Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)

Default:

8008

Declared by:

services.hyperhive.matrix.maxRequestSize

Maximum size in bytes of a single matrix client request body. Default 20 MB matches the matrix-spec recommendation for media uploads + the upstream tuwunel default.

Type: positive integer, meaning >0

Default:

20000000

Declared by:

services.hyperhive.matrix.openFirewall

Open httpPort in the host firewall. Off by default (secure-by-default): the host reaches the homeserver on loopback, and agent containers reach it at matrix.<domain> via the gateway — so the firewall open only matters for access from outside the host. Flip to true when announcing the homeserver to other hives or when an external matrix client needs to reach the client-server API directly.

Breaking change: this used to default to true. If you relied on the old default for external reach, add services.hyperhive.matrix.openFirewall = true; to your host config before rebuilding.

Note: federation (the matrix-spec well-known port 8448) is intentionally not opened here. tuwunel serves the federation API on the same httpPort as the client-server API by default; reaching it on 8448 requires either binding tuwunel to that port explicitly OR a reverse-proxy + .well-known/ matrix/server delegation, neither of which lives in this module. Add that proxy config alongside whatever serves your dashboard or forge on 443.

Type: boolean

Default:

false

Example:

true

Declared by:

services.hyperhive.matrix.registrationTokenFile

Host path to a file containing the matrix registration token tuwunel reads to authorise new-account creation. The token is generated automatically by hive-c0re on first boot (32-byte random hex, mode 0600) and is bind-mounted read-only into the tuwunel container at the same path. Agents never see this token — hive-c0re uses it to provision per-agent accounts and the agent only receives the resulting access_token. Override only when integrating with externally-managed registration tokens.

Type: absolute path

Default:

"/var/lib/hyperhive/matrix-register-token"

Declared by:

services.hyperhive.matrix.serverName

Matrix server_name — the host part of every user ID (@argus:<server_name>) and room ID minted on this homeserver. CRITICAL: must be stable from day one because it’s embedded irrevocably in the identifiers. Defaults to services.hyperhive.domain (the bare hive domain). Combined with the .well-known/matrix/{client,server} routes the hive-gateway serves at that domain, clients auto-discover the actual matrix endpoint without needing a subdomain. Override here only if you need a different server_name shape (e.g. matrix.<domain> if you want the subdomain split, or chat.example.org for a bespoke hostname).

Breaking change: this used to default to matrix.${services.hyperhive.domain}. matrix IDs embed the server_name irrevocably, so existing homeservers must set services.hyperhive.matrix.serverName = "matrix.${services.hyperhive.domain}"; explicitly to preserve their existing user / room IDs before rebuilding.

Type: null or string

Default:

null

Example:

"chat.example.org"

Declared by:

services.hyperhive.matrix.trustedServers

List of trusted matrix servers (homeservers whose signing keys this server will fetch identity-server-style). Empty by default — federation is enabled at the protocol level but no peer is trusted until listed here, so the homeserver is effectively closed until the operator declares hive peers explicitly.

Type: list of string

Default:

[ ]

Example:

[
  "matrix.org"
]

Declared by:

services.hyperhive.network.bridgeIp

IPv4 address assigned to the bridge interface on the host side. Agents use this address as their DNS server (dnsmasq in the gateway container binds here). Default 10.42.0.1 is in RFC 1918 space and unlikely to clash with operator’s existing setup; override if a different range is already in use.

Type: string

Default:

"10.42.0.1"

Example:

"172.30.0.1"

Declared by:

services.hyperhive.network.bridgeName

Name of the host-side bridge interface the hive uses for inter-container traffic. Kept short so it survives the IFNAMSIZ (15-char) cap, and prefixed so it’s obviously hive-managed in ip link output.

Type: string

Default:

"hive-br0"

Example:

"h0"

Declared by:

services.hyperhive.network.bridgePrefixLength

Netmask prefix length for the bridge subnet. Default /24 gives 254 usable per-agent addresses, enough for any single-host hive. Operator with a larger swarm or a tighter addressing scheme overrides.

Type: signed integer

Default:

24

Example:

16

Declared by:

services.hyperhive.network.exposeHostPorts

TCP ports on the host that agent containers may reach at the bridge IP (bridgeIp). Each listed port P is opened on the bridge-interface firewall, so an agent can connect to ${bridgeIp}:P (default 10.42.0.1:P).

Use this to let agents reach a host-local service — e.g. an OpenTelemetry collector for services.hyperhive.otel.endpoint (set endpoint = "http://${bridgeIp}:P").

The host service must bind an address reachable from the bridge0.0.0.0 or the bridge IP (bridgeIp) — not loopback-only. The bridge→127.0.0.0/8 DROP rule (defence-in-depth) is unchanged: this only opens the firewall, it does not bridge loopback. A service that binds 127.0.0.1 only is still unreachable; rebind it to 0.0.0.0.

The exposed port is reachable by EVERY agent on the bridge subnet (same as DNS/gateway), so only expose services safe for any agent to reach.

Type: list of 16 bit unsigned integer; between 0 and 65535 (both inclusive)

Default:

[ ]

Example:

[
  4318
]

Declared by:

services.hyperhive.otel.enable

Whether to enable hive-wide export of every agent’s Claude Code stats (token usage, cost, tool calls) to an OTLP endpoint via Claude Code’s built-in OpenTelemetry. One switch for all agents; each harness exports directly to the collector, so it keeps working even when hive-c0re is down .

Type: boolean

Default:

false

Example:

true

Declared by:

services.hyperhive.otel.debug

Emit OTEL SDK diagnostic messages to every agent’s stderr by setting CLAUDE_CODE_OTEL_DIAG_STDERR=1. Useful when troubleshooting collector connectivity or endpoint config; leave off in normal operation to avoid noise in agent logs. Only meaningful when enable is true.

Type: boolean

Default:

false

Declared by:

services.hyperhive.otel.endpoint

OTLP collector endpoint, set as OTEL_EXPORTER_OTLP_ENDPOINT for every agent. Required when enable is true.

Type: string

Default:

""

Example:

"https://collector.example.com/otel"

Declared by:

services.hyperhive.otel.extraResourceAttributes

Extra comma-separated entries appended to OTEL_RESOURCE_ATTRIBUTES after the built-in service.name / agent / hive / swarm labels.

Type: string

Default:

""

Example:

"deployment.environment=prod"

Declared by:

services.hyperhive.otel.headersCredential

Absolute path to an operator-provided secret file whose contents become OTEL_EXPORTER_OTLP_HEADERS (e.g. Authorization=Bearer <token>). hive-c0re forwards this host file into each agent container’s credential store via systemd-nspawn --load-credential=otel-headers:<path>; the inner harness unit inherits it by name (LoadCredential), so the token is never copied into the nix store, the generated config, a bind mount, or argv. Must be absolute. Leave null if the endpoint needs no auth header. A configured-but-missing file is skipped with a log warning (OTEL still exports, without the auth header).

Type: null or string

Default:

null

Example:

"/run/secrets/otel-headers"

Declared by:

services.hyperhive.otel.metricIntervalMs

Metric export interval in milliseconds, set as OTEL_METRIC_EXPORT_INTERVAL for every agent. Claude Code’s default is 60000 (60s). Leave null to use that default.

Each agent runs claude as a short-lived per-turn process; claude force-flushes metrics on shutdown, so this is not required for metrics to be exported, but a lower value gives more frequent intermediate flushes within long turns. Cosmetic, not a correctness knob.

Type: null or (positive integer, meaning >0)

Default:

null

Example:

10000

Declared by:

services.hyperhive.otel.protocol

OTLP wire protocol, set as OTEL_EXPORTER_OTLP_PROTOCOL.

Type: one of “http/protobuf”, “http/json”, “grpc”

Default:

"http/protobuf"

Declared by:

services.hyperhive.ruthless

Run this hive “ruthless” — with no root (manager) agent at all (no ruth). When true, hive-c0re skips the root-agent auto-management sweep entirely (it otherwise creates the root agent’s container when missing and restarts it when present but stopped). Defaults to false (the root agent is auto-managed as required infrastructure). Exposed to hive-c0re as HYPERHIVE_RUTHLESS.

Type: boolean

Default:

false

Example:

true

Declared by:

services.hyperhive.swarm.peers

Peer hives in the same swarm. The attrset key is the peer’s DNS domain — used for dashboard links and Matrix federation discovery. Null certFingerprint trusts the system CA bundle; set it to pin a self-signed TLS cert. Add wireguardPublicKey + wireguardAddress (and optionally wireguardEndpoint) to include the peer in the WireGuard mesh when swarm.wireguard.enable = true.

Type: attribute set of (submodule)

Default:

{ }

Example:

{
  "edge.corp" = { };
  "lab.example.com" = {
    certFingerprint = "sha256:b1946ac92492d2347c6235b4d2611184a3f5b6cae6c19d6e3c2f0a8e7d4c9f12";
  };
}

Declared by:

services.hyperhive.swarm.peers.<name>.caCert

Path to this peer hive’s root CA certificate (PEM). When set, the CA is embedded (at build time, into the nix store — no runtime file on the host) and trusted everywhere the hive’s own internal CA is: it rides alongside hive-ca.pem in each agent’s security.pki.certificateFiles (via the meta-flake renderer), and is added to the Matrix homeserver container’s trust bundle so tuwunel validates federation TLS from a self-signed peer hive whose cert chains to it. This is the CA-trust path that certFingerprint (leaf-pinning, c0re-only) can’t cover, and is what unblocks Matrix federation with a self-signed peer hive. Trust stays inside the hive (agents + the Matrix container), never the host system trust store. Mutually complementary with certFingerprint; set caCert for the federation case. See docs/swarm.md.

Type: null or absolute path

Default:

null

Example:

"./peers/edge-ca.pem"

Declared by:

services.hyperhive.swarm.peers.<name>.certFingerprint

Expected TLS certificate fingerprint for this peer’s HTTPS endpoint. Null = trust the system CA bundle (for Let’s Encrypt peers). Set to pin a self-signed cert.

Format: the literal sha256: followed by exactly 64 hex digits (case-insensitive, no colon separators) — the SHA-256 digest of the peer’s DER-encoded leaf certificate. Generate with openssl x509 -noout -fingerprint -sha256, then strip the colons and prepend sha256:. A malformed value is ignored with a warning rather than weakening trust. See docs/swarm.md for the full recipe.

Scopes only to hive-c0re’s own peer HTTPS checks — it does NOT help Matrix federation (tuwunel validates against its container trust bundle). For a self-signed peer whose root CA you want trusted hive-wide (every agent + Matrix federation), set caCert below.

Type: null or string

Default:

null

Example:

"sha256:b1946ac92492d2347c6235b4d2611184a3f5b6cae6c19d6e3c2f0a8e7d4c9f12"

Declared by:

services.hyperhive.swarm.peers.<name>.wireguardAddress

IP address (with prefix) of the peer host on the WireGuard mesh. Used as the allowedIPs for the peer’s WireGuard config entry and injected into HYPERHIVE_PEERS so hive-c0re can route intra-swarm traffic to the mesh address rather than the public domain. Required to include the peer in the WireGuard mesh (peers missing this field are silently excluded from wg-hive).

Type: null or string

Default:

null

Example:

"10.100.0.2/32"

Declared by:

services.hyperhive.swarm.peers.<name>.wireguardEndpoint

WireGuard endpoint for this peer in host:port form. Required when the peer host is behind a firewall and this host needs to initiate the tunnel. Null = this host waits for the peer to connect (peer-initiates; peer must have an endpoint pointing back at this host).

Type: null or string

Default:

null

Example:

"203.0.113.1:51820"

Declared by:

services.hyperhive.swarm.peers.<name>.wireguardPublicKey

WireGuard public key for this peer host. Required when services.hyperhive.swarm.wireguard.enable = true and you want this peer reachable over the mesh. Null = TLS- only peering (public internet, no mesh tunnel).

Type: null or string

Default:

null

Example:

"base64pubkey="

Declared by:

services.hyperhive.swarm.wireguard.enable

Enable the WireGuard inter-hive mesh. When true, a wg-hive interface is brought up connecting to all swarm peers that declare a wireguardPublicKey. Requires privateKeyFile to be set.

Type: boolean

Default:

false

Declared by:

services.hyperhive.swarm.wireguard.address

IP address (with prefix) of this host on the WireGuard mesh. Use a /24 (or broader) prefix so the routing table covers all peer /32 routes. Example: "10.100.0.1/24" for a 256-host mesh.

Type: string

Default:

""

Example:

"10.100.0.1/24"

Declared by:

services.hyperhive.swarm.wireguard.listenPort

UDP port the local WireGuard interface listens on. Must be reachable from peer hosts when they initiate the tunnel. Default: 51820 (standard WireGuard port).

Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)

Default:

51820

Declared by:

services.hyperhive.swarm.wireguard.persistentKeepalive

Seconds between keepalive packets sent to each peer. Useful when this host (or a peer) is behind NAT — keeps the UDP hole open. Set to null to disable. Default: 25 seconds.

Type: null or signed integer

Default:

25

Example:

25

Declared by:

services.hyperhive.swarm.wireguard.privateKeyFile

Path to the host’s WireGuard private key file. The file must be readable by root and should have mode 0400. Generate with wg genkey > /etc/wireguard/hive.key. Required when swarm.wireguard.enable = true.

Type: null or absolute path

Default:

null

Example:

"/etc/wireguard/hive.key"

Declared by:

services.hyperhive.swarmName

Human-readable name of the wider swarm this hive belongs to. Hives at different DNS domains can share a swarm name when they federate together. Exposed to agents as HYPERHIVE_SWARM_NAME; surfaced in the dashboard chrome and per-agent system prompt when set.

Type: null or string

Default:

null

Example:

"constellat1on"

Declared by:

services.hyperhive.tls.caValidityDays

Validity window of the hive CA in days (default ~20y). Kept long and well beyond leafValidityDays so the CA outlives many leaf rotations — the whole point of the CA is to be a stable anchor that consumers trust once. The CA is regenerated only if missing or already expired.

Type: signed integer

Default:

7300

Declared by:

services.hyperhive.tls.leafValidityDays

Validity window of the gateway leaf cert in days (default 30). Short-lived by design — ahead of the CA/Browser-Forum’s move toward ~47-day max lifetimes — which bounds the blast radius of a leaf-key compromise. The leaf is re-signed by the (stable) CA when it is missing or near expiry; because it shares the CA anchor, a rotation does not disturb consumer trust. Agents and federation peers validate against the CA, not browser CA/B-forum limits. The weekly hive-tls-resign timer re-signs the leaf once it is within half its validity of expiry and propagates the new leaf into the running gateway, so a long-uptime host renews automatically without a reboot.

Type: signed integer

Default:

30

Declared by:

services.hyperhive.tls.stateDir

Host directory holding the hive CA + gateway leaf cert for the self-signed gateway mode. ca.pem (the anchor agents and federation peers trust), ca-key.pem (0600, never leaves the host), gateway.pem / gateway-key.pem (the leaf the gateway container bind-mounts and nginx serves). Persistent so the CA survives reboots — re-deriving it would re-break every consumer.

Type: string

Default:

"/var/lib/hive-tls"

Declared by: