Menu

Self-hosting

tnnl is built to be self-hosted. Run the tunnel server and PostgreSQL — and, for the full experience, Caddy as the TLS front door and the Next.js dashboard — with Docker Compose.

The components

  • tunnel server — accepts public traffic and the CLI control connection, and serves the API.
  • PostgreSQL — stores users, sessions, and tunnel metadata; enables login auth and the API.
  • Caddy — the TLS front door that terminates HTTPS for the wildcard and custom domains.
  • Next.js dashboard — the web UI for managing accounts and tunnels.
$ docker compose up -d

Pointing the CLI at your server

The hosted tnnl.uz is the default the CLI talks to. To use your own server, point the CLI at it with the TUNNEL_SERVER (control host:port), TUNNEL_API_URL, and TUNNEL_WEB_URL environment variables — or the equivalent --server, --api, and --web flags.

Server configuration flags

These are the tunnel-server binary flags:

FlagDescription
--domainBase domain; subdomains are allocated under it.
--http-portPublic HTTP port (default 8080).
--control-portCLI control connection port (default 7000).
--bindBind address (default 0.0.0.0).
--public-ipServer public IP; enables custom-domain DNS verification.
--no-tlsServe plaintext, e.g. when Caddy terminates TLS.
--acme / --acme-email / --acme-domainBuilt-in ACME for a fixed hostname set.
--database-urlPostgres connection; enables login auth and the API.
--api-portAPI port (default 4000).
--default-admin-user / --default-admin-passwordSeed the first superadmin.
--tokenLegacy shared secret when running without a database.
--inspect-ring-capRetained requests per tunnel (default 50).
--inspect-body-capCaptured body bytes (default 32768).
--cli-install-baseBase URL the CLI installs/upgrades from (env TNNL_CLI_INSTALL_BASE).

DNS

Point a wildcard *.yourdomain (and the apex) at the host so subdomains route. TLS for the wildcard is typically handled by Caddy via a DNS-01 challenge, while custom domains use on-demand TLS.

Database migrations

Database migrations run automatically on server boot.

Building from source
Building from source requires the Rust toolchain. Production images are built in CI and pulled by the host — the host never compiles.