Connections
Use your own tunnel or domain
Reach your server at full quality through Tailscale, a Cloudflare Tunnel, or your own reverse proxy, with no port forwarding.
If your provider won't let you open a port, or you simply prefer not to, you can point tofa at an address you already control. Apps then connect through it at full quality, with none of the relay's bandwidth caps.
This is one line of configuration on the tofa side. Add the address under Admin, Settings, Remote Access, Custom access URLs, and we advertise it to your apps as another direct path. Everything else on this page is about getting that address to exist in the first place.
This adds a path, it does not replace one
Your apps race every path they know about and use whichever answers first. A tunnel sits alongside local playback, port forwarding, and the relay. If the tunnel is down, playback still works.
What the address has to look like#
We validate the URL when you add it, so it is worth knowing the rules up front. The address must:
- use
https://, with a certificate a normal browser trusts. Plain HTTP is rejected, because secure clients cannot reach it. - point at the server's root.
https://tofa.example.comis fine,https://example.com/tofais not. tofa does not serve under a sub-path. - carry no query string, fragment, or embedded username and password.
- not sit behind a second login. Cloudflare Access, an authentication proxy, or HTTP basic auth in front of the server will block both our reachability check and every app. tofa does its own authentication; that is what the address is for.
- pass WebSocket connections through. Apps hold a live connection for playback state and library updates.
A port is allowed if you need one, for example
https://tofa.example.com:8443. You can add up to three addresses, which is
useful if you run both a tunnel and your own domain.
Tailscale#
The quickest option if the only people watching are you and your own devices. Tailscale gives your server a name and a real certificate on your private network, and nothing is exposed to the public internet.
Usually there is nothing to configure
If Tailscale is installed on the machine running tofa, and tofa can see it
(running directly on the machine, or in a container on the host network), we
find the tailnet address on our own and advertise it for you. Your apps pick
it up on the next check-in, and Remote Access shows it as a private network
path. You do not need the tailscale serve step or a custom access URL.
The one case that still needs the manual steps below is a container on a bridge network, which cannot see the host's tailnet address at all.
-
Install Tailscale on the machine running tofa, and on every device you want to watch on. There are apps for iPhone, iPad, Apple TV, Android, and Android TV. There is no Tailscale app for webOS or Tizen televisions, so the built-in TV apps cannot use this path.
-
In the Tailscale admin console, turn on MagicDNS and HTTPS Certificates.
-
On the server, publish tofa on your tailnet:
tailscale serve --bg --https=443 http://localhost:33333Run
tailscale serve statusto see the resulting address. It looks likehttps://your-machine.your-tailnet.ts.net. -
Add that address under Custom access URLs.
Only tailnet devices can use it
People you share your server with are not on your tailnet, so they keep using the relay unless you invite them to it. If you want a path that works for everyone, use a tunnel or your own domain instead.
Tailscale Funnel makes a tailnet service public, but it routes your traffic through Tailscale's own infrastructure and is not built for sustained video. We do not recommend it for streaming.
Cloudflare Tunnel#
A public hostname that works for everyone you share with, and needs no open port. Read the note at the end of this section before committing to it.
-
Install
cloudflaredon the machine running tofa and sign in:cloudflared tunnel login cloudflared tunnel create tofa -
Point a hostname at the server's root. In your
cloudflaredconfig:tunnel: <your-tunnel-id> credentials-file: /root/.cloudflared/<your-tunnel-id>.json ingress: - hostname: tofa.example.com service: http://localhost:33333 # no path, the server's root - service: http_status:404 -
Create the DNS record and run the tunnel as a service:
cloudflared tunnel route dns tofa tofa.example.com cloudflared service install -
Leave WebSocket support on, and do not put a Cloudflare Access policy in front of the hostname.
-
Add
https://tofa.example.comunder Custom access URLs.
Cloudflare's terms limit video through their network
Cloudflare restricts serving large amounts of video and other non-web content through their proxy on their free and lower-tier plans. Streaming a library through a tunnel is exactly that, and people have had tunnels throttled or shut off for it. It works well when it works, but it is worth knowing the risk before you rely on it. A plain reverse proxy on a VPS, or a port forward, carries no such condition.
Your own reverse proxy#
If you already run Caddy, nginx, Traefik, or a bundle like SWAG, point a hostname at the server and add it. With Caddy the whole configuration is:
tofa.example.com {
reverse_proxy localhost:33333
}
Caddy handles the certificate, WebSocket upgrades, and streaming responses on its own. With nginx, three settings matter and are easy to miss:
location / {
proxy_pass http://127.0.0.1:33333;
# WebSockets: live playback state and library updates
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
# Video must stream through, not be collected first
proxy_buffering off;
proxy_read_timeout 600s;
}
Buffering is the one that bites: with it on, nginx tries to collect each video segment before passing it along, and playback stalls or starts slowly.
Check it worked#
Open Admin, Settings, Remote Access. Each address you add is listed with a badge. We probe it from the cloud on the server's next check-in, so a new address turns Verified within about a minute.
A Tailscale address never gets a verdict, and that is fine. We probe from
outside your network, and a .ts.net name or any other private address is only
reachable from inside it, so there is nothing for us to reach. Those entries
show Private network instead, or Not verified yet on older versions.
Neither means anything is wrong: devices on your tailnet still connect through
the address at full quality. The rest of this section is about public
addresses, such as a tunnel or your own domain.
If a public address stays Not verified yet, work through the list at the top of this page. The usual causes are a login sitting in front of the server, a certificate the probe doesn't trust, or a tunnel pointed at a sub-path rather than the root.
Once it is verified, or once your device is on the tailnet, play something away from home and open the quality menu. The relay notice should be gone, and the full quality ladder available. That is the proof it is being used, rather than just being reachable.
Prefer to keep it in your compose file?
The TOFA_CUSTOM_ACCESS_URLS variable takes the same addresses, separated
by commas. Anything set in Settings wins over the variable.
Related#
- Local, direct, or relay explains the three paths and the other ways to get a direct one.
- Run your tofa server covers the server side of remote access.
- What your server sends covers what leaves your network on each path.