global.deploymentMode: saas.
Do not confuse this with the hosted SaaS model, where NeuralTrust operates
both planes and there is nothing to install. Here the chart renders a control
plane that behaves like the hosted one, but it is yours and it runs in your
environment.
Choose it when a single Self-hosted install
cannot work because data has to stay where it was produced — separate business
units, jurisdictions, or environments — but the console, alerting, and
cross-cluster reporting have to be in one place. If every workload fits in one
cluster, Self-hosted is simpler. If NeuralTrust hosts the control plane, use
Hybrid.
Architecture
What runs in your central cluster
This mode is a superset of Self-hosted (chart modeexternal): everything a
self-hosted install deploys, plus three
components and one behaviour change. PostgreSQL and Redis are recommended
managed, outside the cluster; ClickHouse stays in-cluster on the central
side only. Each remote cluster has its own recommended PostgreSQL and Redis —
raw payloads are stored only in the cluster that produced them. The Firewall is
NeuralTrust-hosted by default: TrustGuard sends it the text to score, and it
stores nothing.
External baseline (also here)
Additions that make it a control plane for other clusters
The behaviour change is in DataCore: it runs with a hybrid residency backend
rather than reading the local ClickHouse for everything, so entitled reads go
out through DataBridge to the cluster that holds the data.
The console, ClickHouse, AlertEngine, the bootstrap administrator, and the
datastore split all behave exactly as in
Self-hosted — this page covers only what a
control plane for other clusters adds on top.
Select the topology
Two values, on the central cluster:global.controlPlane.domain is what remote clusters dial. Leave it empty to keep
using NeuralTrust SaaS through global.saasRegion.
Cross-cluster endpoints
The chart derives all four endpoints from that one suffix:
One value drives all four deliberately. A remote cluster that reached DataBridge
on your domain but still dialled NeuralTrust for config-sync would half-work, and
the half that broke would be silent.
Set the same
global.controlPlane.domain on the central cluster and on every
remote cluster. DNS, certificates, and load-balancer provisioning for these names
are operator prerequisites.
There are no NeuralTrust hostnames or IPs anywhere in this topology, and no
NeuralTrust inbound source IP — you own both ends.
Network rules
From each remote cluster (egress): allow TCP 443 to all four endpoints above on your own domain, plus the container registry (or mirror), the LLM upstreams, and that cluster’s own PostgreSQL and Redis. Every cluster running TrustGuard, the central one included, also needs 443 to the NeuralTrust-hosted Firewall (firewall.neuraltrust.ai or firewall.us.neuraltrust.ai, or Private Service
Connect) unless it runs the Firewall itself.
Remote planes keep raw payloads in that cluster’s PostgreSQL and export
metadata over OTLP to https://telemetry.<domain>
(TELEMETRY_EXPORTERS_METADATA=otlp, TELEMETRY_EXPORTERS_RAW=postgres), so
the central ClickHouse holds metadata and the console reaches raw payloads on
demand through DataBridge.
Into the central cluster (ingress): it publishes those four endpoints, so it
accepts inbound TCP 443 on each. Restrict them to the egress ranges of your
data-plane clusters rather than leaving them open, and prefer an internal
load-balancer scheme when the callers are on a private network — see
Cloud notes. Where a link is private, you can skip publishing a
config-sync Service at all with
<product>.configSync.expose.enabled: false.
Nothing here has to traverse the internet. VPC peering, a Transit Gateway or
Direct Connect all work, and a private path is what makes the chart’s own
certificates a sound choice — see TLS.
Two of these carry long-lived streams. If an egress proxy or middlebox in the
path reaps idle connections, config-sync and DataBridge drop and reconnect on
that interval — check its idle timeout. A TLS-intercepting proxy breaks
certificate verification unless its CA reaches the client: put it in the same
bundle you point dataagent.databridge.tlsCa, <product>.configSync.tlsCa and
global.clickstack.egress.tlsCaSecretName at, since each of those replaces the
system roots rather than adding to them.
Prerequisites
Have these ready before installing. Everything else the chart does for you.
The central cluster is also a full self-hosted install, so the Self-hosted
prerequisites apply to it: 3 nodes of 8 vCPU / 16 GiB with the
NeuralTrust-hosted Firewall, or 4 of 8 vCPU / 32 GiB with the Firewall in
your cluster, as the minimum of an autoscaled node pool, the
gcr-secret image pull
Secret, an onprem-superadmin Secret for
the first console administrator, and a decision on the console hostname before
install. Each is covered in
Self-hosted → Prerequisites.
Images
A central cluster pulls two images beyond the External set, both from the NeuralTrust registry and both covered by thegcr-secret pull secret you already
have — databridge, and opentelemetry-collector-contrib for the ingest
gateway. The collector is the same image and tag your Hybrid clusters run as
their egress sidecar, so a mirror that already carries it needs nothing new.
Mirroring for an air-gapped install works the same as everywhere else, and
global.imageRegistry covers both of these. See
Images and registries.
TLS
All four endpoints are dialled from other clusters, and each terminates TLS itself. So each needs a certificate covering its hostname, and each remote cluster needs to accept it. There are three ways to get there, and you can mix them per endpoint.
Which option fits depends on how your remote clusters reach the control plane.
A certificate the data planes already trust
If the data planes traverse the public internet, or you run an internal PKI whose root is already in their trust stores, supply the certificates:Chart-generated, for a control plane on a private network
When remote clusters arrive over VPC peering, Direct Connect or a private link, no public trust store is involved and there is nothing to buy. Let the chart mint every certificate and distribute the CA as configuration:global.controlPlane.domain reaches the certificates. Rerun the export
script after any such change.
Keeping an endpoint off a load balancer
To reach a config-sync listener over peering without publishing a Service at all, set<product>.configSync.expose.enabled: false and route to the ClusterIP
yourself.
For endpoints that do get a load balancer, prefer an internal scheme when the
callers are on a private network — see Cloud notes.
Telling data planes apart
DataBridge has to know which data plane is which. Two authentication modes do that:
Mint one enrolment token per remote data plane, each with its own instance ID.
Reusing a single token across clusters collapses them into one identity in every
query result and audit trail, and nothing later signals that it happened.
Secrets
Five credentials come from the shared platform Secret and are generated for you when the chart owns secrets:
If you pre-provision secrets yourself —
global.preserveExistingSecrets,
global.autoGenerateSecrets: false, or global.platformSecret.existingSecret —
all five must be present, and the two token keys must hold one identical value.
When they drift, every agent connection returns 401 with nothing visibly wrong on
either side. Omitting CONFIG_SYNC_SIGNING_SECRET fails later and further away:
DataCore answers POST /v1/admin/credentials with HTTP 501 not implemented, so
the console’s private-gateway wizard breaks after it has already created the
gateway row. Running ./create-secrets.sh with DEPLOYMENT_MODE=saas writes all
five correctly, including the alias.
Taking the platform Secret out of play in this mode is rejected at render time
rather than at runtime, so a mistake here surfaces during helm upgrade instead
of on first traffic.
The firewall key is the one credential that comes from NeuralTrust. Your
console does not issue firewall keys, so ask NeuralTrust for one per cluster
that runs TrustGuard — the central cluster and each remote one. NeuralTrust sends
each over a secure channel; store it as trustguard-firewall (key
FIREWALL_JWT) and set trustguard.firewall.jwtExistingSecret.name. A cluster
that runs the Firewall itself (global.firewall.deploy: true) needs none.
See Secrets for how the shared platform Secret
works generally.
Remote data planes
Each remote cluster is an ordinary Hybrid install pointed at your domain instead of at NeuralTrust:global.controlPlane.domain takes the place of global.saasRegion for every
connection to the control plane, so leave the region unset. To install a single
product per remote cluster, follow the
TrustGate data plane
or TrustGuard data plane
guide with this change.
Its enrolment and config-sync tokens are issued by your console, not by
app.neuraltrust.ai. Its firewall key, if it
runs TrustGuard, comes from NeuralTrust (see Secrets). Everything
else — the operator-supplied Secrets, the values file, verification, exposing
both TrustGate entry points — is the ordinary
Hybrid install, with
global.controlPlane.domain set and only the Firewall host to allow among the
NeuralTrust hostnames.
Trusting a chart-generated control plane
Only needed when the central cluster serves chart-generated certificates. Apply the bundle produced byscripts/export-controlplane-ca.sh, then point all three
dialling legs at it:
global.customCaCert provides. The telemetry collector configures TLS from its own
config file and ignores that mount, so it takes a Secret name instead.
Before rolling out, confirm from inside each remote cluster that it can reach all
four central endpoints. A data plane whose egress is blocked does not crash — it
starts cleanly, serves its last-known-good configuration, and quietly stops
receiving updates. See Network rules.
Cloud notes
Nothing in the chart is cloud-specific; the LoadBalancer Services take free-form annotations. On EKS with the AWS Load Balancer Controller:trustguard.configSync.expose. GKE already gives a layer 4
passthrough load balancer for a plain LoadBalancer Service; its private
equivalent is networking.gke.io/load-balancer-type: "Internal", and on AKS it is
service.beta.kubernetes.io/azure-load-balancer-internal: "true".
Three things worth knowing on any cloud:
- Use a layer 4 load balancer for DataBridge and config-sync. Both carry long-lived gRPC streams with TLS terminated in the pod. A layer 7 load balancer would have to re-terminate, and its idle timeout will cut streams that are healthy but quiet.
- The ingest gateway is plain HTTP, so it goes through an Ingress and a layer 7 load balancer is fine. It is the only one of the four that is not layer 4.
- An internal scheme keeps the whole topology off the public internet, which is what makes chart-generated certificates a sound production choice rather than a shortcut.
Install
Start from the maintainedneuraltrust-platform
chart, then layer your platform, domain, ingress, TLS, and datastore choices:
Verify
Verify the central cluster on its own before any remote cluster dials it. A remote plane that enrols against a half-configured control plane fails in ways that look like network faults.databridge and clickstack-ingest-gateway. If either is absent,
global.deploymentMode is not saas — and nothing else about the install will
look wrong, because every other component is shared with External.
Then confirm the four cross-cluster endpoints have addresses and that DNS
resolves to them. Three are layer-4 Services and one is an Ingress, so they
appear in different places:
databridge.<domain>, agentgateway-configsync.<domain>, and
trustguard-configsync.<domain> — are what point at them.
Those DNS records are an operator prerequisite the chart cannot check. Until each
name resolves, remote clusters cannot enrol; and because config-sync and
DataBridge retry, the symptom is a remote data plane that stays Running but
never becomes Ready, with nothing wrong on the central side.
Sign in to the console and create the organisation exactly as in
Self-hosted → Verify; the console is the
same install here.
Then enrol one remote cluster
Bring up a single remote data plane as a canary. Two log lines on the remote side prove both directions of the topology, and both are worth reading before the rest of the clusters follow:
Finish with the validation checklist,
which covers the parts no
kubectl command reaches: TLS from the remote
clusters, one enrolment identity per data plane, LLM and MCP traffic, and
telemetry arriving in the central ClickHouse.
High availability
This topology has two availability questions, and they are not equally urgent. The data planes matter most, because they are on the request path. Each remote cluster climbs the standard ladder — one cluster across zones first, then twin clusters, and only for regional loss an active/passive or active/active pair.High availability
The four tiers, from one cluster across zones to two active regions, the two invariants, and exactly what you change in the chart.
The central cluster
Most central clusters should sit on tier 1: one cluster across three zones with managed stores. It is not on the request path, so a promotion runbook is rarely worth its own operational cost. If a regional requirement forces tier 3, run it as an Self-hosted active/passive pair — same shape, same ClickHouse caveat, same promotion steps. Two things are specific to a central cluster.databridge.<domain>, telemetry.<domain>, and the two config-sync
hostnames. Those names must resolve to the promoted cluster’s load balancers, so
plan the DNS switch as part of the runbook. DataBridge streams and config-sync
reconnect on their own once DNS converges; there is nothing to restart in the
remote clusters.
Certificates must be valid from both central clusters. Chart-generated
certificates are minted per cluster with a per-cluster CA, so a remote cluster
that trusts only the primary’s bundle fails every handshake after a promotion.
Either install both bundles in every remote cluster, or issue the four
certificates from your own PKI.
The platform Secret must be identical in both central clusters.
ENROLMENT_SIGNING_SECRET and TELEMETRY_JWT_PRIVATE_KEY_PEM sign the enrolment
and OTLP tokens every remote agent presents. If each cluster generates its own,
tokens minted by one are rejected by the other and every remote agent returns
401 after a promotion. Pre-provision the Secret and apply the same one to both —
see Secrets.
Next steps
Hybrid
The install every remote data-plane cluster runs.
Self-hosted
The baseline your central cluster is built on.
Config sync
How remote products pull configuration from your control plane.
Secrets
Credential handling, including the four cross-cluster keys.
Validation checklist
What to prove before the install counts as done.