feat(#1867): make the internal forge mandatory (remove forge.enable)

The internal forge is the canonical store for the meta flake, every
agent's config repo, and the internal/* repos, so it can no longer be
optional. Remove the services.hyperhive.forge.enable toggle:

- hive-forge.nix: drop the `enable` option; the forge config now
  deploys gated on `services.hyperhive.enable` (it ships with hyperhive).
- hive-c0re.nix: HIVE_FORGE_URL env unconditional; forge-public-URL gate
  drops the enable check (keeps behindGateway).
- hive-gateway.nix: local /etc/hosts forge entry keyed on behindGateway.
- hive-ci.nix: drop the now-moot `forge.ci.enable requires forge.enable`
  assertion (forge is always present); reword the option doc.
- nix/docs/default.nix: drop the `forge.enable = mkForce false` stub
  (option gone); the options-doc eval stays light via hyperhive.enable.
- hive-c0re forge.rs / hivectl.rs: reword 'forge.enable = true' error
  text to 'wait for hive-c0re to start the container' (the runtime
  token-absent path is unchanged — it's a bootstrap-timing check, not
  the opt-out).
- docs/approvals.md, docs/ci.md: drop stale forge.enable references.

Migration: configs that set `services.hyperhive.forge.enable = false`
must drop the line — the forge is now mandatory.

Prereq/companion to #1838 (PR-based config flow, which assumes the forge
is always present).
This commit is contained in:
atlas 2026-06-22 19:26:34 +02:00
commit 2b4e928afe
9 changed files with 37 additions and 58 deletions

View file

@ -109,11 +109,11 @@ let
if stylixThemeColors != null then themedFrontend stylixThemeColors else cfg.frontend;
in
{
# The forge is part of the standard install — hive-c0re mirrors
# every agent's applied config repo into it. On by default; opt out
# with `services.hyperhive.forge.enable = false`. hive-matrix is
# opt-in (off by default) and asserts that `services.hyperhive.domain`
# is set before it can be enabled.
# The forge is mandatory — hive-c0re mirrors every agent's applied
# config repo into it and it's the canonical store for the meta flake
# + `internal/*` repos, so there's no enable toggle; it deploys with
# hyperhive itself. hive-matrix is opt-in (off by default) and asserts
# that `services.hyperhive.domain` is set before it can be enabled.
imports = [
./hive-ci.nix
./hive-forge.nix
@ -790,10 +790,11 @@ in
// lib.optionalAttrs (config.services.hyperhive.swarmName != null) {
HYPERHIVE_SWARM_NAME = config.services.hyperhive.swarmName;
}
// lib.optionalAttrs config.services.hyperhive.forge.enable {
// {
# In-cluster forge URL — the gateway vhost (`forge.<domain>`), which
# nginx proxies to forgejo. Set directly: this env only exists when
# hyperhive is enabled. See `docs/gateway.md::HIVE_FORGE_URL`.
# nginx proxies to forgejo. The forge is mandatory, so this is
# unconditional (the whole env block is already gated on hyperhive
# being enabled). See `docs/gateway.md::HIVE_FORGE_URL`.
HIVE_FORGE_URL = "http://${config.services.hyperhive.forge.domain}";
}
// lib.optionalAttrs config.services.hyperhive.matrix.enable {
@ -823,19 +824,16 @@ in
# dashboard doesn't need to learn the gateway is unconditional.
HIVE_GATEWAY_ENABLED = "1";
}
//
lib.optionalAttrs
(config.services.hyperhive.forge.enable && config.services.hyperhive.forge.behindGateway)
{
# Public URL of the forge vhost served by hive-gateway. The
# dashboard uses this to build browser-facing forge links
# instead of hardcoding `<hostname>:3000`, which breaks when
# the operator accesses the dashboard through the gateway
# (forge sub-domain has no port; direct port URL would be
# wrong). Absent when `behindGateway = false` — dashboard
# falls back to `<hostname>:3000`.
HIVE_FORGE_PUBLIC_URL = "https://${config.services.hyperhive.forge.domain}";
}
// lib.optionalAttrs config.services.hyperhive.forge.behindGateway {
# Public URL of the forge vhost served by hive-gateway. The
# dashboard uses this to build browser-facing forge links
# instead of hardcoding `<hostname>:3000`, which breaks when
# the operator accesses the dashboard through the gateway
# (forge sub-domain has no port; direct port URL would be
# wrong). Absent when `behindGateway = false` — dashboard
# falls back to `<hostname>:3000`.
HIVE_FORGE_PUBLIC_URL = "https://${config.services.hyperhive.forge.domain}";
}
// lib.optionalAttrs (config.services.hyperhive.swarm.peers != { }) {
# Peer hives serialised as a JSON array of {domain, cert_fingerprint,
# wireguard_address?} objects. Consumed by hive-ag3nt::identity::peers()

View file

@ -193,8 +193,8 @@ in
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; `services.hyperhive.forge.enable = true` is
a prerequisite (enforced by assertion).
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.
@ -265,16 +265,9 @@ in
};
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = forgeCfg.enable;
message = ''
services.hyperhive.forge.ci.enable = true requires
services.hyperhive.forge.enable = true the runner registers
against the hive-forge Forgejo instance.
'';
}
];
# No forge-presence assertion needed: the internal forge is mandatory
# (deploys with hyperhive), so the runner always has an instance to
# register against.
# Create /run/hive-ci/ on the host and seed runner-token with a
# placeholder. hive-ci-prefetch.service overwrites it with the real

View file

@ -41,19 +41,11 @@ in
# `/var/lib/nixos-containers/hive-forge/var/lib/forgejo/` survives
# restart. See `docs/gateway.md::hive-forge container shape`.
# The internal forge is mandatory — it's the canonical store for the
# meta flake + every agent's config repo (and the `internal/*` repos),
# so there is no enable/disable toggle. It deploys whenever hyperhive
# itself is enabled (`services.hyperhive.enable`).
options.services.hyperhive.forge = {
enable = lib.mkOption {
type = lib.types.bool;
default = true;
description = ''
Run hive-forge a private Forgejo (in a nixos-container) for
hyperhive agents. On by default: hive-c0re mirrors every
agent's applied config repo into the forge's `agent-configs`
org, so the forge is part of the standard install. Set
`services.hyperhive.forge.enable = false` to opt out.
'';
};
httpPort = lib.mkOption {
type = lib.types.port;
default = 3000;
@ -192,7 +184,7 @@ in
};
};
config = lib.mkIf cfg.enable {
config = lib.mkIf config.services.hyperhive.enable {
assertions = [
{
assertion = cfg.rootUrl == null || lib.hasSuffix "/" cfg.rootUrl;

View file

@ -1019,9 +1019,7 @@ in
networking.hosts = lib.mkIf (cfg.localHostsEntry && hyperhiveDomain != null) {
"127.0.0.1" = lib.unique (
[ hyperhiveDomain ]
++ lib.optional (
(config.services.hyperhive.forge.enable or false)
&& (config.services.hyperhive.forge.behindGateway or false)
++ lib.optional (config.services.hyperhive.forge.behindGateway or false
) config.services.hyperhive.forge.domain
++ lib.optional (matrixCfg.enable && matrixCfg.gatewayHost != null) matrixCfg.gatewayHost
);