Self-hosted service
polius/FileSync avatar
polius/FileSync

FileSync: one-to-many browser transfers over WebRTC, self-hosted with Docker

Send files from one device to many in real-time.

1,578 stars147 forksJavaScriptMIT

At a glance

What is it?
FileSync is a self-hosted MIT-licensed tool that streams files directly between browsers over WebRTC, with a server that only brokers the handshake. The design is sound for LAN and small-group sharing, but the HTTPS requirement and the TURN relay range are the parts to plan for before adopting it.
Who is it for?
Adopt FileSync if you control a server with a public domain and can terminate HTTPS, and you regularly need to push large files to several recipients without accounts. Skip it if plain HTTP on a trusted LAN is your only option and you expect transfers beyond roughly 500 MB, because the Blob fallback buffers the whole file in memory.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The gap FileSync fills: one sender, many browsers, no accounts

Most file transfer tools assume a single recipient. You upload to a server, send a link, and the other side downloads. That model breaks down when you want to hand the same file to five people in a room, or to a phone and a laptop at once, without asking anyone to install an app or create an account. FileSync's README frames the goal directly: send files from one device to many, in real time, private and peer-to-peer, with no size limit. The intended user is someone who can run a Docker container and wants recipients to do nothing more than open a link or scan a QR code. The room model is the core idea. When you open the FileSync URL you land in a room with a unique link and a QR code, and you share that room with as many devices as you want. Anyone in the room sees files appear and can download them. Optional password protection is per room, added before the link is shared. This is a different shape from a link-per-file service, and it is the reason the project exists rather than being a thin wrapper over an existing transfer tool.

How the transfer actually moves: WebRTC data channels plus a brokering server

The README states that FileSync uses native WebRTC to transfer files directly between devices, peer-to-peer, with the server only brokering the initial handshake and never seeing file contents. That split matters for both privacy and cost: the Docker image you run is not a storage server, so disk and bandwidth on your host are not consumed by file payloads in the normal case. The server's job is the handshake plus TURN credential signing. The README notes that every deployment needs a secret key because it signs the TURN credentials used for NAT traversal, and the configuration table says SECRET_KEY signs TURN credentials and tokens and must match the coturn --static-auth-secret. That is the one hard coupling in the stack: two services sharing a static secret. Connection setup runs over port 3478, TCP and UDP. When a direct path fails, traffic falls back to a TURN relay on UDP ports 50000 through 50100. The README estimates that relayed traffic covers roughly 5 to 10 percent of connections, typically a peer behind symmetric NAT or a UDP-blocking firewall. Treat that figure as the project's own documentation, not an independently measured number. The practical consequence is that the relay range is sized for a minority of sessions, and a deployment that blocks those UDP ports will still work for most peers while failing silently for the ones that needed the relay.

Getting it running: two Compose files and one required variable

There are two documented deployment paths. Option A is HTTP for a local network or a quick start, using deploy/docker-compose.yml. Option B is HTTPS for a public domain, using deploy/docker-compose-ssl.yml plus deploy/Caddyfile, with Caddy obtaining and renewing a Let's Encrypt certificate automatically. Both paths require a secret key, generated with a command the README gives: python3 -c "import secrets, base64; print(base64.b64encode(secrets.token_bytes(32)).decode())". The generated value must replace both <SECRET_KEY> placeholders, one on the coturn --static-auth-secret line and one on SECRET_KEY. The README warns explicitly to use your own generated value and never ship the examples. Startup is docker compose up -d for the HTTP setup, or docker compose -f docker-compose-ssl.yml up -d for the HTTPS setup, and teardown is the same commands with down. For the HTTPS path you also edit the Caddyfile, replacing yourdomain.com with your own domain in a reverse_proxy block pointing at filesync:80. SECRET_KEY is the only environment variable listed for the filesync service, it has no default, and the README states the app will not start without it. To change the HTTP port, edit the first number of the port mapping, for example "8080:80", and leave the container port at 80. For a non-standard HTTPS port, the README says to keep Caddy on 443 and put your own reverse proxy in front, terminating TLS there and forwarding to FileSync's internal HTTP port.

The HTTPS requirement is the real constraint, not the file size

FileSync's no size limit claim depends on how the receiving browser saves the file. The README documents three methods, tried in order. First, the File System Access API streams straight to a file the recipient picks, available on desktop Chromium browsers over HTTPS. Second, a Service Worker streams into a normal browser download, available in all modern browsers over HTTPS. Third, a Blob buffers the entire file in memory before saving. The first two require a secure context, meaning HTTPS or localhost. The Blob path is the only option over plain HTTP, and the README calls it unreliable past roughly 500 MB. So the size limit is not a property of WebRTC or of the server. It is a property of the browser context the recipient is in. A deployment on plain HTTP will work fine for small files and degrade as transfers grow, with the failure showing up as memory pressure on the receiving device rather than a clean error. The README states this plainly in the Option A section, noting that large transfers over about 500 MB are unreliable over plain HTTP and pointing to Option B instead. Anyone planning a LAN-only deployment should read that as the deciding factor, not as a footnote.

Where FileSync is the wrong tool

Two cases stand out. The first is a recipient who cannot stay in the browser tab. WebRTC transfers depend on the receiving page being open and connected; there is no server-side inbox holding the file until someone gets to it. If you need to send a file to someone who may open it hours later, a link-per-file service or plain object storage is a better fit, because the file persists independently of any live connection. The second case is a network that blocks the TURN relay ports. The README's port table lists 50000 through 50100 UDP as the relay range, and the note explains it carries traffic for the connections that cannot go direct. If your firewall or your recipients' networks block that range, those sessions have no fallback. The README does not describe a second relay transport, so there is no documented workaround short of opening the range. A third, softer limitation: the room model means access control is per room and password-based. The README describes adding a password before sharing the link, and does not describe per-recipient identity, revocation, or audit logging. For a team that needs to prove who received which file, this is not the tool.

How it differs from server-mediated transfer tools

The clearest comparison is against tools that store the file on a server and hand out a download link. Those tools make the server the source of truth: the upload completes, the file sits on disk or in object storage, and any number of recipients can pull it whenever they like. FileSync inverts that. The server brokers a WebRTC handshake and signs TURN credentials, and the bytes move between browsers. That means no storage cost on the host and no copy of the file on the server, which is the privacy property the README emphasizes. It also means the sender's browser has to stay connected for the duration of the transfer, and the transfer succeeds or fails in real time rather than being queued. The trade-off is availability versus custody. If your recipients are online at the same time and you want to avoid putting the file anywhere, FileSync's approach is the right one. If your recipients are asynchronous, or you need a durable record that the file was delivered, a server-mediated tool gives you something FileSync deliberately does not.

Maintenance surface and licence

The operational surface is small. One Docker image, one Compose file, one Caddyfile for the HTTPS path, one required environment variable, and a coturn secret that must stay in sync with SECRET_KEY. The README documents no database, no persistent volume for file payloads, and no migration step between versions. Upgrades therefore reduce to pulling a new image and restarting the stack, though the README does not describe a version compatibility policy or a changelog for the 4.0.0 release, so the release notes are the place to check before jumping a major version. The port requirements are the part most likely to need attention from whoever manages the firewall: 80 or 443 TCP for the interface, 3478 TCP and UDP for connection setup, and 50000 through 50100 UDP for relay. The project is MIT licensed, which permits commercial and private use and modification, and the README states the licence in a badge and a section. That is a permissive licence, and it also means there is no warranty and no support obligation from the author. This is not legal advice; if you are deploying inside a regulated environment, have your own counsel review the MIT terms and any obligations your organisation has around data that never touches your servers.

Editorial conclusion

Adopt FileSync if you control a server with a public domain and can terminate HTTPS, and you regularly need to push large files to several recipients without accounts. Skip it if plain HTTP on a trusted LAN is your only option and you expect transfers beyond roughly 500 MB, because the Blob fallback buffers the whole file in memory. Before rollout, verify three things: that SECRET_KEY matches the coturn --static-auth-secret, that ports 3478 TCP+UDP and 50000-50100 UDP are open, and that your browser reaches the File System Access API path over HTTPS.

Official sources

  1. License: MIT
  2. polius/FileSync on GitHub
  3. Project website
  4. README
  5. Releases
Community notes

Community notes