Deployment across real network boundaries¶
The reference topology — the shape DIP proved: one well-known central service, per-flow firewall exceptions:
technical network (fieldnet) office networks (officenet, ...)
────────────────────────────── ─────────────────────────
field servers ──multicast──► local consumers, by name
│ (fan-out costs nothing) ▲
│ │ unicast
└────────► relay host ────pinhole──────────────┘
▲
registry: one host, reachable from both sides (HTTP)
Rules of thumb¶
- Multicast never crosses a boundary. Inside one network it is the cheapest possible fan-out; between networks it is neither routable in practice nor auditable. Don't fight that — relay.
- One relay route per stream, one config file per boundary. The relay's
JSON is the pinhole inventory: reviewable, versionable, exactly like
DIP's firewall port ranges but per-stream and self-documenting
(
GET :4860/api/healthshows every route with live counters). - The registry is HTTP on one port — the only thing that needs to be
reachable from everywhere, like the DIP name server today. It is advisory:
its outage stops browsing and first-ever lookups, never data. For
DIP-style redundancy run two and set
HYPERNOVA_REGISTRY=http://reg1:4850,http://reg2:4850— publishers register with both, lookups fail over in order. - Register per-network endpoints so lookup answers depend on where the subscriber sits:
hypernova register site/area1/pump7/env \
--address opc.udp://239.10.0.1:14840 \
--endpoint officenet=opc.udp://10.147.0.5:24840 \
--publisher-id 42 --writer-group-id 100 --dataset-writer-id 1 \
--field temperature=DOUBLE --field fanSpeed=INT32
Consumers on the technical network subscribe to the multicast group;
consumers elsewhere run hypernova sub ... --network officenet and get the
relayed unicast endpoint.
Relay configuration¶
{
"routes": [
{
"name": "site/area1/pump7/env",
"from": "opc.udp://239.10.0.1:14840",
"to": ["opc.udp://10.147.0.5:24840", "opc.udp://10.147.0.6:24840"],
"ttl": 1
}
],
"health_port": 4860
}
The relay never decodes what it forwards (it cannot corrupt a stream) and is
stateless: restart is recovery. Run one instance per boundary host under
systemd/supervisor; watch idleSeconds per route for silence.
Address plan¶
Pick one multicast range per network (e.g. 239.192.x.y — organization-local
scope), one group+port per publishing server, distinct
publisherId per server, and writer-group/dataset-writer ids per stream —
the same discipline as supernova's config.xml. The registry's collision
refusal enforces uniqueness of both names and stream tuples.
Security posture¶
Frames can carry an HMAC-SHA256 signature in the Part 14 SecurityHeader —
sign at the publisher, or at the boundary relay the moment a stream leaves
the trusted network; subscribers with a key reject unsigned frames outright
(require_signed). Multicast inside a trusted network stays unsigned by
default; every inter-network flow is an explicit relay route on a controlled
host. Limits (no replay window, no encryption yet) are stated honestly in
security.md.
Failure drill¶
| Symptom | Where to look |
|---|---|
| name unknown at subscribe | hypernova browse — is it registered? sub waits within --timeout for late registration |
| browser row stale on the technical network | publisher down, or wrong ids in the registration (the registry listens on the group — if the publisher is up, compare ids) |
| stale only beyond the boundary | relay route: check :4860/api/health counters and idleSeconds |
| values but wrong field names | field list in the registration is out of order vs the publisher's config |
| registry down | data unaffected; browsing and first lookups gone — restart it; state is registry.json |
--interface (pub/sub CLI, interface= in the API, HYPERNOVA_INTERFACE env):
pins multicast egress/membership to one local address — required on
dual-homed hosts (a machine with feet in two networks) and for
loopback-only testing (--interface 127.0.0.1).