Skip to main content
Traffic reaches a universe through a load balancer. It holds the certificate for your domain, terminates HTTPS, and forwards to the engine. The machine behind it is not reachable from the internet. On the two cloud grounds, the Terraform creates the load balancer for you, configured to the requirements below. On your own hardware, you bring one.

If you bring your own front door

The shipped modules already satisfy all four of these. They exist for the on-premises case, where your terminator is yours, and the first one is the one that gets missed. Idle timeout of an hour or more. The platform holds long-lived connections for streaming and live updates, and most proxies default to 60 seconds, which severs them. Where the timeout is capped below that, as DigitalOcean caps it at 600 seconds, clients must reconnect cleanly, and that belongs in your acceptance test. Access logs off, for now. A proxy logs full URLs, and one of the platform’s connections still carries its token in the query string. Until that moves to a header, the logs are a place a token could land. This is tracked and will be lifted. Health checks against /health. Nothing else. Forward 443 to :4105. The engine is the only thing the internet ever reaches. None of these make the front door load bearing for security. The authentication gate is inside the application, so swapping one terminator for another is always a contained change.

Ports

Canvas has a door per audience. Operators reach it directly from a nominated address, in the same trust ring as SSH. A POC that turns on canvas_public also serves it through the load balancer over HTTPS, and each cloud page shows exactly how: Both grounds reach it at canvas.<domain> on 443: AWS host-routes it on its single ALB, DigitalOcean gives it a load balancer of its own because DO load balancers cannot route on the hostname.

How a node reaches an external service

Your nodes run inside the engine, and when one calls an API it makes an ordinary HTTPS request straight out of the VM. There is no API gateway, no egress proxy and no broker in between. That is a deliberate choice. A gateway would be another component to run, another place for credentials to sit, and another thing between a failing call and the person debugging it. The controls live where the call is made instead. Every host is declared. A node package lists the hosts its nodes may call. The list is deny-by-default and HTTPS-only, so a node cannot reach anywhere that is not written down. The list is checked twice. Once when the package is linted, and again at run time after the URL has been built from your settings and the incoming data. The second check is the one that matters: it means a node cannot assemble its way to an undeclared host from a template, because the check happens on the final URL rather than on the pattern. A credential never travels in clear text. A request carrying one to a non-HTTPS URL is refused outright rather than downgraded. The node holds no key. Credentials are decrypted at the moment of the call and handed to that node alone. A node receives only what it declared, so two nodes in one workflow cannot read each other’s keys. A reviewer sees the list before it runs. Publishing a node shows the hosts it wants to call, and a node that later reaches for a new one goes back to pending rather than through. So the question a security review usually asks, which is what stops a third-party node calling somewhere it should not, has an answer that does not depend on network equipment. The allowlist is part of the node’s definition, it is sealed into the content hash with everything else, and it is enforced on the request itself. Nodes are documented for developers in Who Can Run It and Credentials.

What a universe must reach outbound

A universe is not a closed system. Four destinations are hard requirements, and an egress-restricted network has to allow them explicitly. Each provider’s Terraform states them. The npm one is worth reading twice. A universe installs node packages at run time, with the database as the record of what should be installed. A blocked registry does not fail loudly at deploy, it produces a universe that comes back from a restart missing capability.

Client applications

Embeds, chat widgets and demo channels are static builds. They have no server and no secrets, they never run on the universe VM, and they never open a port. They talk to the same public surface as everything else. Signed-in users authenticate against your identity provider, and anonymous visitors arrive through a workflow whose trigger allows it. When you host one, a single input has to agree in three places: the list of origins. It feeds CORS on the API, the callback and logout URLs on your identity provider’s client, and the frame-ancestors policy where the app is hosted. The end state for these apps is a one-line embed on somebody else’s page, so treat cross-origin as permanent rather than as a development convenience.
Next: Data and State