Documentation
API reference

Start here

Search every guideesc close

Privacy & network

What your server sends, and what stays on it

What your server sends to our services, what stays on your machine, and the settings you control.

8 min read

Your tofa server is yours. It runs on your hardware, your media stays on your disks, and the cloud's job is limited: sign-in, remote access, metadata, and keeping your watch state in sync across your devices. This page explains those connections and the controls available to you. If you find behavior that differs from this guide, tell us.

The short version#

  • Your media files and library listings stay on your server. Filenames and folder paths can be included when you choose to attach diagnostics to a support report. See the note below about retired reporting on older versions.
  • Playback telemetry (who watched what, when, with what errors) stays on your box. It is visible to you as the server owner. It can be included in a support report if you choose to attach diagnostics.
  • The server's own cloud traffic goes to tofa services (api.tofa.tv, and dl.tofa.tv for downloads and updates), and every request to our API is signed with a key that only your server holds. It also connects to anything you set up yourself, such as an import source, a connected library tool, or a notification webhook.
  • Streaming goes directly from your server to your devices. When a direct connection is impossible, an encrypted relay forwards the bytes without inspecting them.
  • Support reports are sent when you ask for help. You choose whether to attach server diagnostics. Automatic daily reports have been retired.
  • A fresh install reports twice that it exists, so we can see where installs break. It carries the platform and version and nothing else, and you can turn it off before first start.

Every connection, in detail#

Heartbeat, every 25 seconds#

The server checks in with the cloud so your apps can find it. The heartbeat carries connectivity and version facts only: your server's local IP, public IP, port, tofa version, platform, update channel, and any custom access URLs you configured yourself. No usernames, no titles, no watch data.

Metadata lookups#

When the scanner finds new files it asks our metadata service to identify them. What is sent is the cleaned-up title guess the scanner derived (for example a name and a year), plus the library's language and country settings. The raw filename and the file path are not part of a lookup. Pornographic content is not supported or permitted by tofa. This is separate from age ratings and parental controls for ordinary films and shows.

Watch state and watchlist sync#

So you can pause on the TV and resume on your phone, the server syncs watch positions to your account. Each record is a numeric catalog ID, a season and episode number where relevant, a playback position, and a completed flag. Titles, filenames, and paths are not part of the payload.

Preferences sync#

Your app settings (subtitle preferences, playback defaults, and similar) sync as a small settings document tied to your account, so a fresh sign-in on a new device feels like yours.

Update checks, every 2 hours#

The server asks whether a newer build exists for its platform and channel, and reports whether an update it applied succeeded or failed (version numbers and a status, nothing else). Apart from the install failure report described below, there is no automatic crash reporting and no automatic log upload in updated servers. Logs reach us through support reports you send; older versions may still send previously enabled daily reports, as explained below.

Install and setup reports#

A newly installed server sends two short messages: one as it starts up, before it opens its port or brings up its database, and one once it is running and accepting connections. Each carries how it was installed (Docker, Windows, a Linux package, and so on), the operating system and processor type, the tofa version, and the update channel. Your IP address is not stored, and nothing about your machine name, your paths, or your library is in it.

The reason the first message is sent before the database starts is that this is where a broken install usually dies. A server that reports a start and never reports being ready is one we know failed, on a platform we can name, without anyone having to file a ticket.

If a new install fails to start, it sends one more message saying which step of startup it stopped in (for example setting up the database, or opening its port) and a short reason: an error code and the start of the error message, at most 300 characters. Before the reason leaves your server, it replaces everything in it that it can recognise as identifying you or your network with placeholders: your user name and machine name, home folder paths, network share and host names, IP addresses, email addresses, and anything that looks like a password or key. We filter it again when it arrives. Folder paths outside your home folder, such as where tofa keeps its data, can remain in it, because they are usually what explains the failure. If the server stops too abruptly to send anything, its next start reports only the step it stopped in. Each kind of failure is reported once, and a server that has started successfully never sends a failure report again.

While a server is not yet connected to an account, it also counts how often its setup page turned away a request from outside your local network, by kind only: a Tailscale-style address, a public IPv4 or IPv6 address, or a public web address in the browser's address bar. It sends those counts at most every 15 minutes, and once more when you connect it. The addresses themselves are never recorded or sent. This tells us how often people get stuck at setup.

Only fresh installs send the start, ready and failure messages: a server that updates to a newer version, or a working server that restarts, does not send them again. Setup counts come only from servers not yet connected to an account, and stop once you connect. All of these are identified by your server's own key rather than by you, though that key becomes linked to your account if you go on to connect the server, so this is pseudonymous rather than anonymous and we would rather say so plainly.

To switch all of it off, set TOFA_INSTALL_PING=0 in the server's environment. Set it before you start the server for the first time to send nothing at all.

Support diagnostics#

Automatic playback digests and daily health snapshots have been retired. Older server versions may still send reports if those settings were enabled; the cloud discards these reports without storing them or sending digest emails. If your server still shows daily-report settings, turn them off.

Support reports. The Report a problem button on the Server Logs page collects health and log details and opens a support ticket. You choose what to include. Logs can contain file paths and titles from your library, so look over the report before you send it.

Remote access and UPnP#

For remote streaming your server needs a reachable port. tofa tries, in order: a UPnP port mapping request to your router, then PCP, then NAT-PMP. This is a single TCP port mapping for the server's port, renewed every 30 minutes. It is a request to your own router, not an announcement to the network.

Local discovery on your home network#

So your apps can find the server instantly on your own network, the server advertises itself over mDNS (the same Bonjour mechanism printers use) as _tofa._tcp.local.. The advertisement never leaves your local network and carries connection facts only: the server's display name, its version, its port, whether it serves TLS, its local address, and its server ID. No account data, no tokens, and nothing about your library.

You can turn it off in Admin, Settings (the lan_discovery_enabled setting); it stops advertising immediately, no restart needed. If you deploy with environment variables instead, TOFA_LAN_DISCOVERY=false keeps it off regardless of the setting.

Things tofa deliberately does not do on your LAN:

  • No SSDP or DLNA advertising. Your server does not announce itself over SSDP, and there is no DLNA media server in tofa.
  • One listening port (33333 by default), nothing else.

To turn automatic port mapping off entirely, set a manual external port in Admin, Settings, Remote Access (the manual_external_port setting). That tells tofa you forward the port yourself, and the UPnP, PCP, and NAT-PMP code never runs.

If neither a mapped nor a forwarded port is reachable, streaming falls back to our relay. The relay is a pipe: it forwards the encrypted bytes between your device and your server and does not decrypt or inspect what you watch.

Permissions on your machine#

  • On macOS, the menu bar app runs the server as your user, not as root. The optional "Run at Boot" mode installs a system service with one admin prompt, and even then the server process runs under your account. The terminal installer works the same way: it asks for your password to register the service, then runs the server as you, and it refuses to install if it can't tell which user that should be.
  • On Linux, the installer asks for your password because it creates a dedicated unprivileged tofa system user, installs to /opt/tofa, and registers a systemd service that runs as that user, locked down with systemd's sandboxing (no new privileges, read-only system, writable only in its own folders). The server never runs as root.
  • On Windows, the installer needs admin once to install; the server itself then runs in your session as your user, unelevated.
  • In Docker, the container starts as root only long enough to match file ownership to the PUID/PGID you set, then permanently drops to that unprivileged user before the server starts. It never touches the ownership of your media.

Verify it yourself#

You can use a proxy or packet capture to check which services your server contacts. Compare the traffic with the connections above and any integrations you enabled. If something does not match, send us the details so we can check the behavior and correct this guide where needed.