tnl.dev :: docs

security.

Understand encryption, visitor access, and trust boundaries.

where encryption starts and ends

The visitor connects to a public URL over HTTPS. Visitor TLS passes through ingress and relay as encrypted bytes and terminates in the local tnl process. During normal forwarding, ingress and relay cannot read HTTP paths, headers, bodies, or responses. Local tnl decrypts the request and sends it to the local service over HTTP on localhost; that last hop is not TLS.

Encryption does not hide connection metadata. Ingress sees the visitor source IP, the requested hostname in TLS SNI, connection timing, and traffic volume. The connected relay receives source and destination metadata and handles the stream; control receives usage reports. Those are different from the HTTP content inside visitor TLS.

The tnl server controls public URL DNS and certificate issuance. An active operator controlling both could send visitors to another endpoint and obtain a valid certificate to impersonate your URL. Passive forwarding cannot read the HTTP, but visitor TLS does not remove trust in the operator or the certificate authority.

control who can visit

By default, tnl allows the current IP address it sees when you publish. You can allow more addresses or allow all visitors. This IP policy is checked by ingress before forwarding any local-service request. A limited number of denied connections can reach local tnl for TLS termination and an HTTPS 403 explanation; excess denied connections are dropped at ingress. No denied request reaches the local service. IP policy is not visitor authentication: people sharing an allowed address can connect, and IP addresses can change. If an app needs sign-in or per-user access, enforce that in the app. See who can visit.

accounts, teams, and credentials

Your sign-in creates a control session used to manage public URLs. Teams and memberships decide who can use a team's domains and public URLs; they do not log visitors in to your app. Local tnl holds the access and refresh tokens for its session, a publish run token to update one run, and a credential for each assigned publisher connection. It also holds the visitor TLS private key. Keep client state private: someone with those credentials could act as you or publish under your run.

trust boundaries on your machine and server

Only control connects to PostgreSQL and holds the server's DNS and ACME credentials. Split ingress and relays authenticate to control with a cluster secret; leases and connection assignment checks reject stale processes, while ingress uses short-lived routing information. Local tnl checks the visitor hostname and replaces untrusted forwarding headers before sending HTTP to your app. Treat the local service as reachable by anyone your visitor policy admits, unless the app enforces its own access rules.

self-hosted responsibilities

If you run your own server, you operate DNS, certificate issuance, PostgreSQL, and process credentials. Keep control's DNS and ACME credentials and storage key private, and retain the storage key with database backups: without it, encrypted recoverable secrets cannot be restored. In split deployments, protect the cluster secret on all processes that use it. Relay transport certificates secure publisher connections to relays; they do not terminate visitor TLS.