tnl.dev :: docs
operate a tnl server.
Check health, pause new work, and drain relay processes.
check readiness and visitor traffic
Run these checks against your own standalone or split server. Replace control.example.com and the relay identifiers with your deployment's values.
curl --fail https://control.example.com/v1/health
curl --fail https://control.example.com/v1/ready
tnl admin server status --server https://control.example.com
tnl admin relays list --server https://control.example.com/v1/health means the public control HTTP server responds. /v1/ready returns 200 when the database and, if configured, Route 53 credentials are ready, or 503 otherwise; check it through the public control hostname to include public DNS and TLS. It does not check the whole visitor path. tnl admin server status reports the role, ingress and relay lease counts, and ready versus starting publish runs. A live relay lease does not prove a public URL works. Run tnl publish 3000 --server https://control.example.com --allow-all-ips with a local service on port 3000, then request its printed public URL from a visitor to check DNS, certificate issuance, ingress, publisher connections, and the local service end to end. Restrict a non-public test with --allow-ip instead.
Each tnld process also has a private metrics listener (the checked-in Compose files listen on 0.0.0.0:9090 inside the container and only expose port 9090). Its GET /health returns 204 for a live process, GET /ready returns 204 or 503 for that role's readiness, and GET /metrics serves Prometheus data. Scrape over a private network; do not treat metrics readiness as a visitor probe. Review control, ingress, and relay logs alongside lease and certificate state when a public request fails.
pause new work
The three maintenance controls independently gate new public URL creation, new publish run creation, and certificate issuance. Blocking an operation does not stop existing visitor connections. Check state before and after a change:
tnl admin maintenance list --server https://control.example.com
tnl admin maintenance block public_url_creation --server https://control.example.com
tnl admin maintenance block publish_run_creation --server https://control.example.com
tnl admin maintenance block certificate_issuance --server https://control.example.com
tnl admin maintenance list --server https://control.example.comUse tnl admin maintenance allow <name> --server https://control.example.com to reopen each control when ready. Block only the operations your maintenance requires; blocking publish run creation or certificate issuance prevents a publisher from becoming routable.
drain a relay process
In a split deployment, list relays and copy the exact relay ID, process run ID, and lease revision of the process to remove. Drain it with a deadline, then check that publisher connections move to available relay processes before stopping the container:
tnl admin relays list --server https://control.example.com
RELAY_RUN_ID='replace-with-process-run-id-from-list'
RELAY_LEASE_REVISION='replace-with-lease-revision-from-list'
tnl admin relays drain relay-a-1 --relay-run-id "$RELAY_RUN_ID" --relay-lease-revision "$RELAY_LEASE_REVISION" --deadline 30s --server https://control.example.com
tnl admin relays list --server https://control.example.comThe matching run ID and revision keep a stale drain request from affecting a restarted relay. Draining rejects new work and allows existing connections to finish until the deadline; ensure another relay service and capacity remain. Standalone has two logical relay services in one process, so draining one does not give host-level redundancy.
back up and upgrade
Back up external PostgreSQL consistently and test a restore. Store the matching TNLD_STORAGE_KEY securely with the backup: it decrypts recoverable secrets, including certificate material. Keep TNLD_STORAGE_KEY_PREVIOUS during a key rotation until re-encryption has completed; preserve any previous key required by an older backup. Protect .env, login tokens, cluster secrets, and database credentials separately. A database snapshot without its storage key is not a full recovery plan.
Before changing the digest-pinned image, back up the database and keys and read the release and compatibility notes. Run tnld migrate with TNLD_DATABASE_DIRECT_URL for the new release, then start control or standalone with the new image and its TNLD_DATABASE_URL pointing at the pooler. Compose's migrate dependency runs this sequence on up, but it does not back up data or make a mixed-version rolling upgrade safe. Serving processes require the exact schema version they support; schedule a stop/start upgrade rather than letting older control processes use a newly migrated schema. Check /v1/ready, relay leases, and a visitor request after restart. For configuration and port details, see tnld reference.