tnl.dev :: docs

tnld reference.

Commands and configuration for tnld processes.

commands and roles

tnld runs one server process. Configure it with environment variables, tnld serve flags, or a --config YAML/JSON file; serve is the default command. The self-hosting walkthrough includes both canonical Compose files.

CommandPurpose
tnld serveStart the configured role (also the default command).
tnld migrateApply embedded PostgreSQL migrations using only TNLD_DATABASE_DIRECT_URL.
tnld login-tokenPrint one new built-in authority login token; save it privately.
tnld config check --config path/to/tnl.ymlValidate a YAML or JSON process file without starting services; success is silent.
tnld versionPrint version and commit.

TNLD_ROLE / --role accepts standalone (default), control, ingress, or relay. Standalone combines control, ingress, and two logical relay services; its two services do not form separate failure boundaries. Control owns PostgreSQL, certificate issuance, DNS automation, and administration. Ingress accepts visitor TCP connections and forwards each once to a connected relay. Relays accept publisher connections over QUIC or TLS/TCP and carry visitor streams. Split ingress and relay processes require a shared cluster secret; standalone must not be configured with one.

tnld serve --config path/to/tnl.yml loads the tnld section of a versioned .yml, .yaml, or .json configuration file. Explicit flags take precedence over environment variables, which take precedence over file values. tnld migrate does not load serving configuration. See tnld serve --help for serving flags (for example, TNLD_RELAY_ID / --relay-id); TNLD_DATABASE_DIRECT_URL is read only from the environment by migrate.

database and dns

SettingUse
TNLD_DATABASE_URLPooled PostgreSQL URL for control and standalone only; never pass it to ingress or relays.
TNLD_DATABASE_DIRECT_URLDirect PostgreSQL URL read by tnld migrate only.
TNLD_SERVER_DOMAINInfrastructure suffix for control., ingress., and relay hostnames.
TNLD_MANAGED_DEPLOYMENT_DOMAINPublic URL namespace domain, independent of the server domain.
TNLD_ROUTE53_MANAGED_ZONE_IDOptional managed-domain hosted zone for public URL DNS automation. Supply TNLD_INGRESS_IPV4_ADDRESSES and/or TNLD_INGRESS_IPV6_ADDRESSES with it.
TNLD_ROUTE53_SERVER_ZONE_IDServer-domain hosted zone for relay transport certificate DNS-01 issuance.

Control and standalone require the exact supported schema version when they start. Use tnld migrate against the direct connection before serving a new version. The Route 53 zones serve distinct purposes; the checked-in split Compose file requires TNL_SERVER_ZONE_ID and passes it as TNLD_ROUTE53_SERVER_ZONE_ID to control.

listeners and certificates

The defaults are public control :443, private control :9443 for the split control role, public ingress :443 for ingress/standalone, and relay TCP and UDP :443 for relay/standalone. Standalone uses in-process control calls. Use TNLD_CONTROL_LISTEN, TNLD_PRIVATE_CONTROL_LISTEN, TNLD_INGRESS_LISTEN, TNLD_RELAY_TCP_LISTEN, and TNLD_RELAY_UDP_LISTEN to bind them explicitly. TNLD_METRICS_LISTEN defaults to 127.0.0.1:9090; empty disables the private /health, /ready, and /metrics listener. Compose binds its process listeners inside containers at 8443, leaving public host port 443 unchanged.

Split ingress and relays set TNLD_CONTROL_HOSTNAME (DNS name, no scheme or port) and can use TNLD_PRIVATE_CONTROL_ADDRESS (for example, control:9443) to dial the private control API. Each ingress needs a stable TNLD_INGRESS_ID. Each relay needs TNLD_RELAY_SERVICE_ID, TNLD_RELAY_ID, a public TNLD_RELAY_ADDRESS (hostname and port), and a TNLD_INTERNAL_RELAY_ADDRESS reachable from ingress; TNLD_INTERNAL_RELAY_LISTEN binds the internal forwarding port. Restrict private control 9443 and internal relay 9445 to the server network.

Control and standalone require TNLD_ACME_EMAIL, TNLD_ACME_ACCEPT_TERMS=true, and an HTTPS TNLD_ACME_DIRECTORY_URL (default: Let's Encrypt production). TNLD_ACME_PROFILE defaults to tlsserver. Automatic control and public URL certificates use ACME; control may instead use a paired TNLD_CONTROL_TLS_CERTIFICATE_FILE and TNLD_CONTROL_TLS_PRIVATE_KEY_FILE. Relays may use a paired TNLD_RELAY_TLS_CERTIFICATE_FILE and TNLD_RELAY_TLS_PRIVATE_KEY_FILE, or control can issue relay transport certificates using the server-domain Route 53 zone. If standalone uses a static control certificate, also configure relay certificate automation or a static relay pair. Mount static files readably in the container when using the read-only Compose image.

authority and secrets

SettingUse
TNLD_LOGIN_TOKENRequired for control/standalone using the built-in authority. Generate with tnld login-token; do not use it with an external authority.
TNLD_STORAGE_KEYRequired unpadded base64url encoding of a 32-byte key; control/standalone encrypt recoverable PostgreSQL secrets with it. TNLD_STORAGE_KEY_PREVIOUS supports re-encryption during rotation.
TNLD_CLUSTER_SECRETHigh-entropy shared secret on split control, ingress, and relays for private API authentication. TNLD_CLUSTER_SECRET_PREVIOUS is accepted only during rotation.
TNLD_AUTHORITY_ENDPOINTHTTPS origin of an external authority. Requires TNLD_HOSTED_SECRET and OIDC settings; omit TNLD_LOGIN_TOKEN. TNLD_HOSTED_SECRET_PREVIOUS supports rotation.
TNLD_OIDC_ISSUER, TNLD_OIDC_CLIENT_ID, TNLD_OIDC_LOGIN_FLOWComplete OIDC configuration when using OIDC; login flow is device_code or authorization_code_pkce. TNLD_OIDC_SCOPES can supply scopes including openid.
TNLD_PUBLIC_URL_USAGE_URL, TNLD_PUBLIC_URL_USAGE_TOKENOptional paired HTTPS receiver base URL and service token for public URL usage reports.

Never supply control-only database, storage, login, hosted, or DNS-provider settings to an ingress or relay. Keep all secrets and the metrics listener off public networks. See operations for readiness, backups, and safe upgrades.