Watch
0
0
Fork
You've already forked hyperhive
0

swarm-otel: scrape nats through its published name

The queue's metrics were scraped over loopback from the exporter, declared
only where the queue and the collector share a host, so a collector on any
other host had no job for it. Its target is now declared on every host as
`https://<swarm.nats.domain>/metrics`, and the queue's host gets a gateway
vhost on that name serving `= /metrics` from the exporter behind the
collector's auth subrequest (`/__nats_metrics_authz`, the forge's shape).
Every other path there is 403; the monitoring endpoint is never proxied.
The rules derived from `publishedScrapeTargets` admit the collector's
client and deny every other subject. The loopback entry, and with it
`glue-otel-scrape-targets.nix`, is gone.

In self-signed mode the vhost serves the queue's own `swarm-nats` leaf
(issued for exactly that name, `server_flag` set), copied 0640
root:nginx by `swarm-nats-gateway-cert`; until the leaf exists that unit
writes a throwaway pair, so nginx never starts on a missing file. The
name stays out of `swarm.serviceDomains`, so a host whose only swarm
service is the queue fronts no services name and its gateway neither
waits for nor needs the swarm-services leaf: no services-issuer pair has
to be placed on it. With ACME or an operator cert the vhost uses the
gateway's own TLS, as every other name does.

The queue's host now enables the gateway (`mkDefault`), as every other
swarm service's host does.

Fixes #5205
This commit is contained in:
atlas 2026-10-14 20:21:31 +02:00
commit 217b3f1cea
9 changed files with 276 additions and 56 deletions

View file

@ -362,6 +362,74 @@ let
failedAssertions remoteLeafNoUrl == [ ]
&& !(remoteLeafNoUrl.systemd.services.hive-c0re.environment ? HIVE_C0RE_NATS_URL);
}
{
# Only `/metrics`, from the exporter, behind the collector's subrequest:
# no `error_page` (a scraper would parse a login page as metrics), the
# monitoring endpoint never proxied, every other path refused. In
# self-signed mode the vhost names the queue's own leaf, as copied for
# nginx, not the swarm-services one.
name = "the queue's name serves only /metrics, behind the collector's auth subrequest, on the queue's own leaf";
ok =
let
h = allLocal.services.hyperhive;
v = allLocal.services.nginx.virtualHosts.${natsName};
locs = v.locations;
checksOf = l: lib.filter (lib.hasPrefix "auth_request") (lib.splitString "\n" l.extraConfig);
authz = locs."= /__nats_metrics_authz";
in
lib.attrNames locs == [
"/"
"= /__nats_metrics_authz"
"= /metrics"
]
&& locs."/".return == "403"
&& locs."/".proxyPass == null
&& locs."= /metrics".proxyPass == "http://127.0.0.1:${toString h.swarm.nats.metricsPort}/metrics"
&& checksOf locs."= /metrics" == [ "auth_request /__nats_metrics_authz;" ]
&& !(lib.hasInfix "error_page" locs."= /metrics".extraConfig)
&& authz.proxyPass == "https://auth.t.local/api/authz/auth-request"
&& lib.hasInfix "internal;" authz.extraConfig
&& !(lib.any (
l:
lib.hasInfix ":${toString h.swarm.nats.monitorPort}" (
if l.proxyPass == null then "" else l.proxyPass
)
) (lib.attrValues locs))
&& v.forceSSL
&& v.sslCertificate == "/var/lib/swarm-nats-gateway-tls/cert.pem"
&& v.sslCertificateKey == "/var/lib/swarm-nats-gateway-tls/key.pem";
}
{
# A host whose only swarm service is the queue: its gateway serves the
# queue's name with the queue's leaf, fronts no swarm-services name, and
# so neither waits for nor requires the swarm-services leaf. The copy
# unit is only wanted by nginx, never required, and a rotated queue leaf
# re-runs it.
name = "a host running only the queue renders its gateway without requiring the swarm-services leaf";
ok =
let
h = queueNoStore.services.hyperhive;
s = queueNoStore.systemd.services;
copy = s.swarm-nats-gateway-cert;
in
h.deploy.nats.enable
&& !h.deploy.hive-controller.enable
&& h.gateway.enable
&& h.gateway.useSelfSigned
&&
queueNoStore.services.nginx.virtualHosts.${natsName}.sslCertificate
== "/var/lib/swarm-nats-gateway-tls/cert.pem"
&& h.swarm.localServiceDomains == [ ]
&& !(lib.elem natsName h.swarm.serviceDomains)
&& !(lib.elem "hive-gateway-self-signed-cert.service" (s.swarm-services-cert.requiredBy or [ ]))
&& !(lib.hasInfix "serves swarm names only with it" s.hive-gateway-self-signed-cert.script)
&& lib.elem "nginx.service" copy.wantedBy
&& lib.elem "nginx.service" copy.before
&& !(lib.elem "nginx.service" (copy.requiredBy or [ ]))
&& lib.hasInfix "throwaway self-signed" copy.script
&& lib.hasInfix "chgrp nginx" copy.script
&& lib.hasInfix "systemctl start swarm-nats-gateway-cert.service" s.swarm-bao-nats-tls.script;
}
];
in
runGroup "nats-tls" cases