- 🔒 Private by design — files travel directly between browsers over encrypted WebRTC. The server only brokers the initial handshake; it never sees your file contents.
- 🚀 No size limit — received files stream straight to disk, so even multi-gigabyte transfers use almost no memory (over HTTPS — see how files are saved).
- 👥 One-to-many — share a room link or QR code and send to as many devices at once.
- 🌐 Works across networks — connects directly when possible, with automatic STUN/TURN relay fallback for restrictive NATs and firewalls.
- 🪄 No installs, no accounts — recipients just open a link in any modern browser. Optional password protection per room.
- 🐳 Self-hosted — a single Docker image you run yourself.
- Features
- Table of contents
- How to use
- Self-hosting
- Required ports
- Customizing ports
- Configuration
- How received files are saved
- Under the hood
- License
- Open your FileSync URL — you land in a room with a unique link and a QR code.
- Share the link (or QR) with the people or devices you want to send to.
- Drop in your files — drag and drop them (or click Send Files). Recipients see them appear and can download instantly.
Want to restrict access? Click Add password to protect the room before sharing the link.
- Docker and Docker Compose
- Python 3 (only to generate the secret key below)
Every deployment needs a secret key (it signs the TURN credentials used for NAT traversal). Generate one with:
python3 -c "import secrets, base64; print(base64.b64encode(secrets.token_bytes(32)).decode())"
⚠️ Use your own generated value — never ship the examples shown below.
Best for trying FileSync or running it on a trusted LAN. Note that large transfers (>~500 MB) are unreliable over plain HTTP — for those, use Option B.
1. Download deploy/docker-compose.yml.
2. Set your secret. Replace both <SECRET_KEY> placeholders with your generated value:
# (use your own generated value — these are illustrative)
- --static-auth-secret=Hs9k…your-generated-key…=
- SECRET_KEY=Hs9k…your-generated-key…=3. Start it:
docker compose up -dOpen http://localhost (or your server's IP).
Caddy obtains and renews a Let's Encrypt certificate automatically. HTTPS also unlocks memory-safe streaming for files of any size.
1. Download deploy/docker-compose-ssl.yml and deploy/Caddyfile.
2. Set your secret. Replace both <SECRET_KEY> placeholders (same as Option A).
3. Set your domain. In Caddyfile, replace yourdomain.com with your domain:
filesync.example.com {
reverse_proxy filesync:80
}4. Start it:
docker compose -f docker-compose-ssl.yml up -dOpen https://yourdomain.com.
docker compose down # HTTP setup
docker compose -f docker-compose-ssl.yml down # HTTPS setupOpen these on your server/firewall to expose FileSync to the internet:
| Port | Protocol | Purpose |
|---|---|---|
80 (HTTP) / 443 (HTTPS) |
TCP | Web interface |
3478 |
TCP + UDP | STUN/TURN — peer-to-peer connection setup |
50000–50100 |
UDP | TURN relay range — used when a direct connection isn't possible |
Port
3478handles connection setup. The50000–50100UDP range carries relayed traffic for the ~5–10% of connections that can't go direct (typically a peer behind symmetric NAT or a UDP-blocking firewall).
HTTP port. In docker-compose.yml, change the first number of the filesync port mapping (the second is the internal container port — leave it as 80):
ports:
- "8080:80" # serve on http://localhost:8080HTTPS port. Keep Caddy on 443 and put your own reverse proxy (Nginx, Traefik, standalone Caddy) in front if you need a non-standard external port — terminate TLS there and forward to FileSync's internal HTTP port.
Environment variables on the filesync service:
| Variable | Required | Default | Description |
|---|---|---|---|
SECRET_KEY |
Yes | — | Signs TURN credentials and tokens. Must match the coturn --static-auth-secret. The app won't start without it. |
FileSync writes received files to disk as the bytes arrive, so transfers use almost no memory regardless of size. It uses the first method the browser supports, falling back in order:
- File System Access API — streams straight to a file you pick. Desktop Chromium browsers (Chrome, Edge, Brave, Opera) over HTTPS.
- Service Worker — streams into a normal browser download. All modern browsers over HTTPS.
- Blob — buffers the whole file in memory, then saves it. Last resort; the only option over plain HTTP, and unreliable past ~500 MB.
The first two require a secure context (HTTPS, or localhost), so serving FileSync over HTTPS is recommended — it enables memory-safe transfers of any size.
FileSync uses native WebRTC to transfer files directly between devices — peer-to-peer, with no intermediate server in the data path. Your files stay private throughout.
A lightweight WebSocket signaling server (served at /ws by the FileSync app itself) assists only with the initial connection setup — relaying SDP offers/answers and ICE candidates between peers. Once a peer-to-peer connection is established, the signaling server steps back and file bytes flow directly between browsers. The server never has access to file contents.
Released under the MIT License.

