docs: nest config examples and use neutral swarm/hive names
Closes #6146
This commit is contained in:
parent
af434e1374
commit
4c321f3d2d
8 changed files with 113 additions and 77 deletions
|
|
@ -68,11 +68,17 @@ The smallest working config, as in the README's
|
|||
|
||||
```nix
|
||||
services.hyperhive = {
|
||||
deploy.singleHostSwarm = true;
|
||||
deploy.hive-controller.enable = true;
|
||||
swarm.domain = "hive.example";
|
||||
deploy.hive-controller.hiveName = "pr1ma";
|
||||
swarm.hives.pr1ma = { };
|
||||
swarm = {
|
||||
domain = "myswarm.example";
|
||||
hives.firsthive = { };
|
||||
};
|
||||
deploy = {
|
||||
singleHostSwarm = true;
|
||||
hive-controller = {
|
||||
enable = true;
|
||||
hiveName = "firsthive";
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ an agent's config arrive as PRs you merge. → [`2-handbook/agent-lifecycle/agen
|
|||
To create an agent yourself instead, use the swarm UI, or:
|
||||
|
||||
```bash
|
||||
swarmctl agent create iris --hive pr1ma
|
||||
swarmctl agent create iris --hive firsthive
|
||||
```
|
||||
|
||||
The controller provisions iris's identity, forge user and config repo
|
||||
|
|
|
|||
|
|
@ -503,17 +503,21 @@ as the forge or the secret store is down. A restart isn't needed to recover.
|
|||
|
||||
```nix
|
||||
services.hyperhive = {
|
||||
swarm.domain = "example.com"; # required — the swarm's DNS domain
|
||||
deploy.hive-controller.hiveName = "pr1ma"; # required on a hive host — this hive's label in it
|
||||
swarm.name = "constellat1on"; # shared swarm display name (optional)
|
||||
swarm = {
|
||||
domain = "myswarm.example"; # required — the swarm's DNS domain
|
||||
name = "myswarm"; # shared swarm display name (optional)
|
||||
|
||||
# required — the directory, identical on every host in the swarm.
|
||||
# Names only: each entry's `domain` defaults to <name>.<swarm.domain>.
|
||||
swarm.hives = {
|
||||
pr1ma = { }; # this host, per hiveName
|
||||
lab = { }; # a second hive
|
||||
edge = { domain = "edge.elsewhere.example"; }; # addressed off-convention
|
||||
# required — the directory, identical on every host in the swarm.
|
||||
# Names only: each entry's `domain` defaults to <name>.<swarm.domain>.
|
||||
hives = {
|
||||
firsthive = { }; # this host, per hiveName
|
||||
secondhive = { }; # a second hive
|
||||
thirdhive.domain = "thirdhive.elsewhere.example"; # addressed off-convention
|
||||
};
|
||||
};
|
||||
|
||||
# required on a hive host — this hive's label in the directory
|
||||
deploy.hive-controller.hiveName = "firsthive";
|
||||
};
|
||||
```
|
||||
|
||||
|
|
@ -536,9 +540,9 @@ names the missing hive. Peers are _every entry but this host's_, so a
|
|||
directory without this host would make every hive a peer, itself included.
|
||||
|
||||
```
|
||||
# hive A # hive B
|
||||
deploy.hive-controller.hiveName = "pr1ma"; deploy.hive-controller.hiveName = "edge";
|
||||
swarm.hives = { … }; swarm.hives = { … }; # byte-identical
|
||||
# hive A # hive B
|
||||
deploy.hive-controller.hiveName = "firsthive"; deploy.hive-controller.hiveName = "secondhive";
|
||||
swarm.hives = { … }; swarm.hives = { … }; # byte-identical
|
||||
```
|
||||
|
||||
One entry per hive means two hosts can't hold _different_ facts about the
|
||||
|
|
@ -548,7 +552,7 @@ same third hive, such as a stale endpoint.
|
|||
is names only. Set it only for a hive addressed by something else. This
|
||||
hive's own `services.hyperhive.domain` comes from its entry; it drives
|
||||
`HYPERHIVE_HIVE_DOMAIN` in every container so agents can form qualified
|
||||
labels (`iris@pr1ma.example.com`). Setting `services.hyperhive.domain`
|
||||
labels (`iris@firsthive.myswarm.example`). Setting `services.hyperhive.domain`
|
||||
directly overrides the directory entry, with a deprecation warning: the
|
||||
option is local to this host while every host shares the directory, so a
|
||||
value written only here is invisible to the rest of the swarm.
|
||||
|
|
@ -608,42 +612,44 @@ wg pubkey < /etc/wireguard/hive.key # → share this with peer operators
|
|||
#### Config example (two hives)
|
||||
|
||||
```nix
|
||||
# hive A (pr1ma.example.com, mesh IP 10.100.0.1)
|
||||
# hive A (firsthive.myswarm.example, mesh IP 10.100.0.1)
|
||||
services.hyperhive = {
|
||||
deploy.wireguard = {
|
||||
enable = true;
|
||||
enable = true;
|
||||
privateKeyFile = "/etc/wireguard/hive.key";
|
||||
address = "10.100.0.1/24";
|
||||
listenPort = 51820; # optional, default 51820
|
||||
address = "10.100.0.1/24";
|
||||
listenPort = 51820; # optional, default 51820
|
||||
};
|
||||
|
||||
# The same `hives` attrset both hosts hold — mesh fields included,
|
||||
# since "where this hive can be dialled" is a fact about that hive.
|
||||
swarm.hives = {
|
||||
pr1ma = {
|
||||
domain = "pr1ma.example.com";
|
||||
firsthive = {
|
||||
domain = "firsthive.myswarm.example";
|
||||
wireguardPublicKey = "base64keyA=";
|
||||
wireguardEndpoint = "198.51.100.1:51820";
|
||||
wireguardAddress = "10.100.0.1/32";
|
||||
wireguardEndpoint = "198.51.100.1:51820";
|
||||
wireguardAddress = "10.100.0.1/32";
|
||||
};
|
||||
edge = {
|
||||
domain = "edge.corp";
|
||||
secondhive = {
|
||||
domain = "secondhive.elsewhere.example";
|
||||
wireguardPublicKey = "base64keyB=";
|
||||
wireguardEndpoint = "203.0.113.42:51820";
|
||||
wireguardAddress = "10.100.0.2/32";
|
||||
wireguardEndpoint = "203.0.113.42:51820";
|
||||
wireguardAddress = "10.100.0.2/32";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# hive B (edge.corp, mesh IP 10.100.0.2)
|
||||
# hive B (secondhive.elsewhere.example, mesh IP 10.100.0.2)
|
||||
services.hyperhive = {
|
||||
deploy.wireguard = {
|
||||
enable = true;
|
||||
enable = true;
|
||||
privateKeyFile = "/etc/wireguard/hive.key";
|
||||
address = "10.100.0.2/24";
|
||||
address = "10.100.0.2/24";
|
||||
};
|
||||
|
||||
swarm.hives = { /* … identical to hive A's … */ };
|
||||
swarm.hives = {
|
||||
# … identical to hive A's …
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -171,8 +171,10 @@ They derive together: a store with no UI is unreadable and a UI with no
|
|||
store is empty. To run one without the other, set it directly:
|
||||
|
||||
```nix
|
||||
services.hyperhive.deploy.victoriametrics.enable = true;
|
||||
services.hyperhive.deploy.grafana.enable = false;
|
||||
services.hyperhive.deploy = {
|
||||
victoriametrics.enable = true;
|
||||
grafana.enable = false;
|
||||
};
|
||||
```
|
||||
|
||||
⚠️ **This starts a database that grows for as long as the swarm runs.**
|
||||
|
|
|
|||
|
|
@ -153,9 +153,13 @@ Only the swarm's forge host runs it (`services.hyperhive.deploy.forgejo.enable`,
|
|||
```nix
|
||||
# The SSH port is swarm-wide: every hive dials it. The HTTP port and whether
|
||||
# THIS host opens them in its firewall are this host's deployment decisions.
|
||||
services.hyperhive.swarm.forge.sshPort = 2222; # default — git-over-SSH, off the host's openssh on 22
|
||||
services.hyperhive.deploy.forgejo.httpPort = 3000; # default — outside hyperhive's 7000 / 8100-8999
|
||||
services.hyperhive.deploy.forgejo.openFirewall = false; # default
|
||||
services.hyperhive = {
|
||||
swarm.forge.sshPort = 2222; # default — git-over-SSH, off the host's openssh on 22
|
||||
deploy.forgejo = {
|
||||
httpPort = 3000; # default — outside hyperhive's 7000 / 8100-8999
|
||||
openFirewall = false; # default
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
`sshPort` serves `git clone/push/pull` over SSH (`git@<domain>:owner/repo.git` with `-p 2222`). SSH goes straight to Forgejo, not through nginx.
|
||||
|
|
|
|||
|
|
@ -92,10 +92,14 @@ listener sits on `bridgeIp`, on the host's bridge interface.
|
|||
```nix
|
||||
{
|
||||
services.hyperhive = {
|
||||
deploy.hive-controller.enable = true;
|
||||
deploy.hive-controller.hiveName = "pr1ma";
|
||||
swarm.domain = "darkest.space";
|
||||
swarm.hives.pr1ma = { }; # -> domain = pr1ma.darkest.space
|
||||
swarm = {
|
||||
domain = "myswarm.example";
|
||||
hives.firsthive = { }; # -> domain = firsthive.myswarm.example
|
||||
};
|
||||
deploy.hive-controller = {
|
||||
enable = true;
|
||||
hiveName = "firsthive";
|
||||
};
|
||||
# network.bridgeIp = "10.42.0.1"; # default
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,17 +19,19 @@ assumptions:
|
|||
## Enabling it
|
||||
|
||||
```nix
|
||||
services.hyperhive.snapshotStore = {
|
||||
enable = true;
|
||||
path = "/var/lib/hyperhive-snapshots"; # must be on btrfs
|
||||
port = 51821;
|
||||
};
|
||||
services.hyperhive = {
|
||||
snapshotStore = {
|
||||
enable = true;
|
||||
path = "/var/lib/hyperhive-snapshots"; # must be on btrfs
|
||||
port = 51821;
|
||||
};
|
||||
|
||||
# The mesh is a hard requirement, and is asserted:
|
||||
services.hyperhive.deploy.wireguard = {
|
||||
enable = true;
|
||||
address = "10.100.0.9/24";
|
||||
privateKeyFile = "/etc/wireguard/hive.key";
|
||||
# The mesh is a hard requirement, and is asserted:
|
||||
deploy.wireguard = {
|
||||
enable = true;
|
||||
address = "10.100.0.9/24";
|
||||
privateKeyFile = "/etc/wireguard/hive.key";
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -135,8 +135,10 @@ single-host deploy, but are useful for multi-hive or custom-network
|
|||
setups.
|
||||
|
||||
```nix
|
||||
services.hyperhive.agent.forge.url = "http://forge.example:3000"; # default: null
|
||||
services.hyperhive.agent.matrix.url = "https://matrix.example"; # default: null
|
||||
services.hyperhive.agent = {
|
||||
forge.url = "http://forge.example:3000"; # default: null
|
||||
matrix.url = "https://matrix.example"; # default: null
|
||||
};
|
||||
```
|
||||
|
||||
**`services.hyperhive.agent.forge.url`** — base URL of the Forgejo instance. It scopes
|
||||
|
|
@ -179,15 +181,19 @@ The harness installs Claude Code plugins before the serve loop opens.
|
|||
Three per-agent `agent.nix` options control this:
|
||||
|
||||
```nix
|
||||
services.hyperhive.agent.claudeMarketplaces = [ # default
|
||||
"anthropics/claude-plugins-official"
|
||||
"${services.hyperhive.agent.packages.claude-plugins}" # hive's own local marketplace, registered as `hyperhive`
|
||||
];
|
||||
services.hyperhive.agent.claudePlugins = [ # default
|
||||
"skill-creator@claude-plugins-official"
|
||||
"base@hyperhive"
|
||||
];
|
||||
services.hyperhive.agent.claudePluginsAutoUpdate = false; # default
|
||||
services.hyperhive.agent = {
|
||||
claudeMarketplaces = [
|
||||
# default
|
||||
"anthropics/claude-plugins-official"
|
||||
"${services.hyperhive.agent.packages.claude-plugins}" # hive's own local marketplace, registered as `hyperhive`
|
||||
];
|
||||
claudePlugins = [
|
||||
# default
|
||||
"skill-creator@claude-plugins-official"
|
||||
"base@hyperhive"
|
||||
];
|
||||
claudePluginsAutoUpdate = false; # default
|
||||
};
|
||||
```
|
||||
|
||||
- **`claudeMarketplaces`** — list of marketplace sources passed to
|
||||
|
|
@ -248,10 +254,11 @@ programmatically and don't pass `--message-format json` themselves.
|
|||
## API-key provider (`useApiKey` / `backendEnvironmentFile`)
|
||||
|
||||
```nix
|
||||
services.hyperhive.agent.useApiKey = true; # default: false
|
||||
services.hyperhive.agent.backendEnvironmentFile =
|
||||
"/agents/myagent/harness/openrouter.env"; # default: null
|
||||
services.hyperhive.agent.model = "anthropic/claude-3.5-sonnet"; # provider-specific model string
|
||||
services.hyperhive.agent = {
|
||||
useApiKey = true; # default: false
|
||||
backendEnvironmentFile = "/agents/myagent/harness/openrouter.env"; # default: null
|
||||
model = "anthropic/claude-3.5-sonnet"; # provider-specific model string
|
||||
};
|
||||
```
|
||||
|
||||
Runs this agent's `claude` against an API-key provider (for example OpenRouter)
|
||||
|
|
|
|||
Loading…
Reference in a new issue