Install
Run your tofa server
Get your tofa server running in a few minutes on Linux, macOS, Windows, or your NAS.
This guide installs the server, which stores your library and streams it to your devices. To watch on a computer, install the separate desktop player or use app.tofa.tv. If someone has shared their server with you, you do not need to install one.
Quick install#
Pick your platform. Every path ends in the same place: tofa running at
http://localhost:33333, ready to claim with your account. If you installed on
a NAS or another computer, use its network address in place of localhost.
After installation, continue with Claim your server and
Add your media.
The setup we recommend. One line on any machine with Docker, whether that is a Linux box, a NAS, or Docker Desktop:
curl -fsSL https://get.tofa.tv/docker | sh
It is a short, readable script. Open get.tofa.tv/docker in a browser first if you want to read it before you run it. It writes a compose file for one container that manages everything itself, including its own database, asks where your media lives, starts the server, and points you at the claim page.
Prefer to write the compose file yourself? Set it up by hand below walks through every line.
No Docker? tofa also installs natively. Paste one line into a terminal. It downloads the latest build for your machine, sets tofa up as a system service, and opens the claim page:
curl -fsSL https://get.tofa.tv | sh
It is a short, readable script. Open get.tofa.tv in a
browser first if you want to read it before you run it. It asks for your
password because it installs a system service: it creates a dedicated tofa
user, puts the server in /opt/tofa, and registers it with systemd. The
server itself never runs as root. It also verifies the download against a
published checksum before installing anything, and it puts a small tofa
helper command on your PATH (more on that under
Everyday commands).
On an Apple silicon Mac, download tofa for Mac, open it, and drag tofa into Applications. On first launch tofa moves into the menu bar, starts your server in the background, and opens the claim page. From then on it starts with your Mac; nothing sits in your Dock.
The same terminal one-liner as Linux works too, if you prefer it. It asks for your password once to install the app and register the background service, and the server then runs under your account, never as root:
curl -fsSL https://get.tofa.tv | sh
On an Intel Mac, use Docker Desktop and the walkthrough below instead.
Windows has its own installer, so you do not need Docker.
- Download tofa for Windows.
- Run it and accept the prompt to install.
- Open
http://localhost:33333to claim your server.
tofa lives in your system tray and starts when you sign in to Windows.
Everything it needs comes with it, including its own database. Your library
and settings live in C:\ProgramData\tofa.
Because tofa runs as you, it can read any folder you can read, and it stops when you sign out. If you want the server reachable around the clock, leave the machine signed in, or turn on automatic sign-in for the account that runs it.
The installer opens the server's port in Windows Firewall on every network type. If devices at home still can't reach the server directly, check whether other security software on the PC is blocking the port; until it's reachable, streaming rides the relay.
Download the installer only from dl.tofa.tv, and check it against the
.sha256 file we publish next to it:
Get-FileHash .\tofa-beta-windows-x64-setup.exe -Algorithm SHA256
Our Windows builds aren't code-signed yet, so Windows may say it doesn't recognise the publisher. Once the checksum matches, choose More info, then Run anyway.
Uninstalling asks whether to remove your library. Say no and your media database, settings, and artwork stay where they are, ready for the next install.
On an Unraid server, tofa is in Community Applications: open the Apps
tab, search for tofa, and install it. Install on Unraid
covers the paths and permissions worth checking before you click Apply, plus
hardware transcoding.
On a Synology, QNAP, TrueNAS, or any other Docker-capable NAS, use the compose walkthrough below. Your NAS's container app can run it directly: on Synology, open Container Manager, create a Project, and paste the compose file from step 1; on QNAP, use Container Station and its Create Application (compose) option. Three NAS-specific tips:
- Keep tofa's data folder on your fastest storage (an SSD volume if you have one). tofa runs its own database in there.
- If your NAS runs containers as a specific user, set
PUIDandPGIDto that user's ids in the compose file; the builder below has a question for it. tofa fixes up its own data folder's ownership on start and never changes ownership of your media. - On TrueNAS, put tofa's data folder on a dataset with a stripped ACL. If an
inherited NFSv4 ACL gives the group write access, the database can't start,
and
chmodwon't change that.
Set it up by hand#
Prefer to write the files yourself, or want to see what each piece does? The rest of this page is the manual Docker walkthrough. One container runs and manages everything, including its own database and automatic backups, and it takes about ten minutes.
What you need#
- A computer that stays on: a Linux box, a NAS, a mini PC, or a Mac. It doesn't need to be powerful. On an Unraid server, follow Install on Unraid instead.
- Docker with the Compose plugin. If you don't have it, install Docker Engine (Linux) or Docker Desktop (Mac, Windows) from docker.com. Compose is included with both.
- Your media in folders on that machine.
- A tofa account with a verified email address.
The image runs natively on 64-bit Intel and AMD (x86-64) and on ARM, including Apple Silicon and ARM NAS boxes. Docker pulls the right build automatically.
01Build your compose file#
Make a folder for tofa, answer the questions below, and copy the result into a
file named docker-compose.yml in that folder.
Everything here can be changed later, and skipped questions fall back to safe defaults. There are no secrets to set up: on first start tofa generates what it needs, including the key it signs sessions with, and stores it in its own data.
02Start it#
From the folder with your compose file:
docker compose up -d
The first start takes a minute or two while tofa sets up its database. To watch it come up:
docker compose logs -f
Ctrl+C stops the log view, not the server.
03Claim your server#
Open a browser to:
http://localhost:33333
If tofa runs on a different machine (a NAS or a server), use that machine's
address on your network instead, for example http://192.168.1.50:33333.
Sign in with the same tofa account you created at app.tofa.tv and follow the steps to claim your server. Once claimed, continue to Add your media.
Claiming from another device#
For security, a brand-new server only accepts a claim from its own local
network. Opening it on the same machine (localhost) or by its LAN address
(like 192.168.1.50) works out of the box. If the only way you can reach it is
by a hostname, a public address, or through a reverse proxy, the claim page will
refuse with a security notice.
For those cases the installer prints a one-time claim link that carries a setup token and works from anywhere:
http://your-server:33333/setup?setup_token=…
Lost it, or set the server up by hand? The server prints the same link in its own logs on every start while it is unclaimed:
# Docker
docker compose logs tofa | grep setup_token
# Native (systemd)
journalctl -u tofa | grep setup_token
Open that link from any device and claim as normal. The token stops working the moment the server is claimed.
Choose your own setup token#
If you deploy with a script or playbook, you can pick the token yourself
instead of reading it from the logs. Set SETUP_ACCESS_TOKEN in the server's
environment, then build the link from it:
environment:
SETUP_ACCESS_TOKEN: "paste-a-long-random-value-here"
https://tofa.example.com/setup?setup_token=paste-a-long-random-value-here
Anyone holding this token can claim a server that has not been claimed yet, so treat it like a password:
- Make it long and random. We do not enforce a minimum length, but use at
least 32 characters.
openssl rand -hex 32gives you a good one. - Stick to letters, digits,
-and_. The token travels in a link, and characters such as+,&,#,%, or spaces get changed in transit and stop matching. - Surrounding whitespace is ignored. An empty value counts as not set.
When the variable is not set, the server makes a token of its own on first
start and keeps it in identity/setup_key.secret inside its data directory,
so the link stays the same across restarts.
After the claim, tofa gets its secure certificate automatically so your devices can connect directly. There is nothing to restart.
From here you can manage it at this address or from app.tofa.tv.
04Add your media#
In the web interface, add a library and choose your media folder.
On a native install, select the folder on the server machine where your
movies or shows live. On Docker, use the path inside the container:
/media, or a subfolder like /media/Movies. If you mapped extra
folders in your compose file (say /media/TV or /media/Kids), point each
library at the container path you gave it, the right side of the colon. tofa
scans, matches, and fills in artwork on its own.
Return to app.tofa.tv. The first-server page checks automatically when you return and while it is open, so your claimed server should appear without refreshing. If you are still waiting, choose I’ve installed it. Check for my server.
Once your server appears, select it. You can also open any tofa app and sign in with the same account. Let the first scan find your titles, then open one and press Play.
Everyday commands#
If you installed with a get.tofa.tv one-liner (native or Docker), you already
have the tofa helper on your PATH. It detects how your server is installed
and gives you one set of commands everywhere:
| Task | Command |
|---|---|
| Update to the latest beta | tofa update |
| Is it running? What version? | tofa status |
| Follow the logs | tofa logs |
| Restart, stop, start | tofa restart / tofa stop / tofa start |
| Print the local address | tofa url |
If you set Docker up by hand, the compose commands do the same jobs. Run them from the folder with your compose file:
| Task | Command |
|---|---|
| See the logs | docker compose logs -f |
| Stop the server | docker compose down |
| Start it again | docker compose up -d |
| Restart it | docker compose restart |
| Update to the latest beta | docker compose pull then docker compose up -d |
When a new build is out, the Software Update card under Admin, then Settings tells the admin. Linux one-liner, macOS, and Windows installs can apply the update from that card; Docker installs get the matching commands shown instead. Your data and settings survive updates on every platform. The full story, including channels and rollback, is in Keep your server up to date.
Remote access and local playback#
If no direct path is available, apps try the tofa relay. Your server still needs to be running and connected to the internet for remote playback. tofa sets up faster direct paths where it can:
-
At home, devices connect straight to the server over your own network at full quality. On Linux this needs nothing from you. On Docker Desktop tofa can't see your machine's address by itself, so tell it under Settings, then Remote Access, then local network address (the setup wizard's remote access step shows the same control). Prefer keeping it in your compose file? The
ADVERTISED_LAN_IPvariable from step 1 does the same thing. -
Away from home, the server asks your router to open a port automatically (Linux setup). If your router doesn't allow that, forward a port yourself and enter it under Settings, then Remote Access. Otherwise the relay covers it.
-
Through a tunnel or your own domain, if you already have one. Add its address under Settings, then Remote Access, then custom access URLs, and apps use it as a direct path. See Use your own tunnel or domain.
Settings, then Remote Access shows which path is active, and has a test button that checks the home-network address from the device you're on. If it reports carrier-grade NAT or double NAT, automatic port mapping may not be enough; Local, direct, or relay covers what helps.
Backups#
tofa backs up its database on a schedule, keeps the recent ones, and verifies
each backup can be restored. Backups live in the tofa-data volume. You can
see them, take one manually, or restore one under Settings, then Database.
Back up your server covers restores, disaster
recovery, and what to copy yourself.
Put backups on a second disk
By default, backups sit on the same disk as the database. To survive a disk
failure, add TOFA_BACKUP_DIR: /backups under environment: and a line like
/mnt/other-disk/tofa-backups:/backups under volumes:. The Database page
confirms the new location and can move existing backups over.
Use your own PostgreSQL#
tofa runs its own bundled database, and that is the setup we recommend and support. If you would rather use a PostgreSQL server you already run, see Use your own PostgreSQL for what it needs and how to set it up.
Remove tofa#
Removing the program never touches your media files, and your library database is kept unless you delete it yourself, so a later reinstall picks up right where you left off.
Docker. Run docker compose down in the folder with your compose file,
which removes the container and keeps its data. The default compose file
stores your database in a named tofa-data volume. If you used a host folder
instead, the data stays there. Keep that volume or folder to reuse your
library on a later install.
Windows. Uninstall tofa from Settings, then Installed apps, like any other
program. The uninstaller asks whether to remove your library data. Keep it to preserve
C:\ProgramData\tofa for a later reinstall.
macOS. Quit tofa from the menu bar, then paste these lines into Terminal one at a time. Some may answer "No such process", which is fine.
sudo launchctl bootout system/com.tofa.server
launchctl bootout gui/$(id -u)/com.tofa.server.agent
launchctl bootout gui/$(id -u)/com.tofa.tray
sudo rm -f /Library/LaunchDaemons/com.tofa.server.plist
rm -f ~/Library/LaunchAgents/com.tofa.server.agent.plist ~/Library/LaunchAgents/com.tofa.tray.plist
sudo rm -rf /Applications/tofa.app ~/Library/Logs/tofa
If you installed from the terminal one-liner, two small helpers were added that you can remove the same way:
sudo rm -f /usr/local/bin/tofa /etc/tofa/manage.env
Your library database stays in ~/Library/Application Support/tofa; delete
that folder if you don't want to keep it.
Linux package install. Remove the package with your package manager, for
example sudo apt remove tofa on Debian and Ubuntu or sudo dnf remove tofa
on Fedora. Your library data stays in the tofa data directory.
Linux one-liner install. This installs a systemd service, not a package. Stop and disable it before removing the program:
sudo systemctl disable --now tofa.service
sudo rm -f /etc/systemd/system/tofa.service /usr/local/bin/tofa /etc/tofa/manage.env
sudo rm -rf /opt/tofa
sudo systemctl daemon-reload
Your library data stays in /home/tofa/.tofa, and environment overrides stay
in /etc/tofa/tofa.env. Keep both if you plan to reinstall.
If something is off#
-
The page won't load at
localhost:33333. Give it another minute on the very first start, and checkdocker compose logs -ffor a line saying it's listening. If Docker is on another machine, use that machine's IP, notlocalhost. -
The claim page refuses with a security notice. A new server only accepts a claim from its local network. Reach it by its LAN address (like
http://192.168.1.50:33333) from a device on the same network, or use thesetup_tokenlink from the installer output or the server logs. See Claiming from another device. -
Port 33333 is already in use. Move tofa to a free port by setting the environment variable
TOFA_PORT, for exampleTOFA_PORT: 34000in your compose file'senvironment:block. The server then listens, advertises, and is reached on that port everywhere, browser and apps alike. A Docker port remap ("34000:33333") also works for the browser, but the server doesn't know about the outside number, so apps are still told to connect on 33333. If you remap instead of settingTOFA_PORT, put the outside port in Settings → Remote Access → Local network address asaddress:portso apps hear the right one. -
My media isn't showing up. Every media line is
host-path:container-path, with a colon between the two. A line missing the colon (like- /mnt/mediaor- /mnt/media/TV/) makes Docker create an empty throwaway volume instead of mounting your files, so tofa sees an empty folder. Check that the left side is the real path on your machine, that the folder has files in it, and that every media line keeps its colon. To confirm tofa can see the files, rundocker exec tofa ls /media(ordocker exec tofa ls /media/TVfor a folder you mapped): it should list your shows and movies, not come back empty. -
Playback at home feels limited or slow. Use the test button under Settings, then Remote Access. If the address isn't reachable, correct the local network address on that same page. It should be your machine's address on your home network, not an address from inside Docker. (
ADVERTISED_LAN_IPin your compose file sets the same thing.) -
The logs warn that
/dev/shmis small, or mentioncould not resize shared memory segment. tofa's database keeps working memory in/dev/shm, and Docker gives containers only 64MB of it unless told otherwise. Compose files from before October 2026 don't set it. If you installed with the one-line Docker installer, run it again from where you first ran it (the folder that holds thetofafolder, not thetofafolder itself, and with the sameTOFA_DIRif you set one). For a compose file it wrote, it adds these for you, keeps a copy of your old file, and restarts tofa. Otherwise add these lines undertofa:, next torestart:, then rundocker compose up -d:shm_size: 512m ulimits: nofile: soft: 65536 hard: 65536shm_sizeis a ceiling, not memory set aside, andulimitslets the server keep enough files open on a large library. Withdocker run, the same settings are--shm-size=512m --ulimit nofile=65536:65536.
Still stuck? Getting help & feedback covers what to send us.