diff --git a/nix/host-modules/hive-c0re/environment.nix b/nix/host-modules/hive-c0re/environment.nix index 3046f46c..ba345ca8 100644 --- a/nix/host-modules/hive-c0re/environment.nix +++ b/nix/host-modules/hive-c0re/environment.nix @@ -81,15 +81,39 @@ in # don't render no-op env lines. let otel = config.services.hyperhive.otel; + # `otel.endpoint` keeps meaning "where telemetry ultimately goes", + # on every hive, whether or not a collector runs. What changes with + # a collector is only where the *first* hop lands — so the + # agent-facing value is DERIVED here rather than by redefining the + # option. Redefining it would migrate the meaning of a value every + # existing hive already has set, silently, while still evaluating. + # With the collector off this expression is `otel.endpoint`, i.e. + # byte-identical to before the collector existed. + collectorOn = otel.collector.enable; in { - HYPERHIVE_OTEL_ENDPOINT = otel.endpoint; - HYPERHIVE_OTEL_PROTOCOL = otel.protocol; + HYPERHIVE_OTEL_ENDPOINT = + if collectorOn then + "http://${config.services.hyperhive.network.bridgeIp}:${toString otel.collector.port}" + else + otel.endpoint; + # The first hop is the collector's OTLP/HTTP receiver, which speaks + # protobuf regardless of what the upstream wants — `otel.protocol` + # describes the *upstream* link, and the collector's own exporter is + # what has to honour it (see nix/host-modules/otel.nix). + HYPERHIVE_OTEL_PROTOCOL = if collectorOn then "http/protobuf" else otel.protocol; } // lib.optionalAttrs (otel.extraResourceAttributes != "") { HYPERHIVE_OTEL_EXTRA_RESOURCE_ATTRIBUTES = otel.extraResourceAttributes; } - // lib.optionalAttrs (otel.headersCredential != null) { + // lib.optionalAttrs (otel.headersCredential != null && !collectorOn) { + # This is the variable that puts the upstream token in an agent's + # own `~/.claude/settings.json` (host_config.rs forwards it into the + # container as an nspawn credential; claude-settings.nix's + # `hive-otel-header` oneshot then writes it into a file the agent + # can read). Not emitting it is what actually removes the token from + # agent containers — the collector holding the credential is only + # half of it, and the half that is invisible in a diff. HYPERHIVE_OTEL_HEADERS_CREDENTIAL = otel.headersCredential; } // lib.optionalAttrs (otel.metricIntervalMs != null) {