The use case is that people host microservices on their Hydra, some of which need to be publicly reachable. The mechanics of the path are proven — district hub -> venue tunnel -> Pi LAN address -> Incus proxy device -> scale, measured at HTTP 200 in 73 ms. Automating ingress is tracked separately.
This issue is for the questions that automation does not answer, and which should be decided before anything customer-facing is switched on.
If tenants bring their own domain they CNAME to the district server and autocert issues a certificate on first request. Two consequences:
HostPolicy must check registration, not merely accept whatever arrives, or the box becomes an open ACME client and will hit Let's Encrypt rate limits.Decide: are domains only ever *.experiencenet.com subdomains we control, or do we accept customer domains? The second needs a verification step (DNS TXT or similar) before a route is honoured.
The Pi is LAN-private behind NAT, so the mesh is the only inbound route and the hub is always on the path. That means:
brussels-district-v2 on the public path for customer workloads. That is the box whose backup is still unproven (#422), whose snapshots fail roughly 1 in 5 silently (#424), and which also runs hydraneckwebrtc and the WireGuard hub for 24 peers.Decide whether public workloads should terminate somewhere other than the district hub, or whether the hub is hardened and monitored first.
hydrareverseproxy builds one httputil.NewSingleHostReverseProxy per domain. There is no pool, no health check and no failover: a scale that dies is a 502 until someone notices.
That is tolerable for internal tools and weak for anything customer-facing. It also interacts with the state problem — most Hydra services are single-writer YAML stores, so "just run two" would split writes and diverge. Capacity and availability need state solved first, or need services that are genuinely stateless.
Scales inherit 512 MiB memory and 5 GiB disk caps, kernel-enforced (verified: a 700 MB allocation in a 512 MiB scale is OOM-killed inside its own cgroup, node unaffected). But CPU is deliberately unbounded — limits.cpu in Incus is cpuset pinning rather than a share, and pinning would cripple Go services by forcing GOMAXPROCS=1.
So one tenant's busy scale can starve a neighbour's. Acceptable between internal services on a node we control; a different proposition when tenants are paying.
Also note disk caps only work because btrfs quota enable is run at provision time — without it a size: is accepted silently and enforces nothing.
If tenants deploy their own images they need to push somewhere. Today scaleregistry.experiencenet.com has a single shared credential distributed to nodes, with no per-tenant namespacing and no per-repository authorisation. Related maturity work is #427.
For completeness, the rejected option: making scales full WireGuard mesh members would give every scale reachability from all 24 peers — iPads, Windows air units, venue routers. Public hosting does not need internal reachability, and this would widen exposure considerably for no benefit to this use case. Recorded so the decision is not revisited by accident.
Start with *.experiencenet.com subdomains only, allocated by us, on services we operate. That removes questions 1 and 5 entirely and makes the ingress automation useful immediately. Revisit customer domains and tenant image pushes only once ownership and verification exist.