Contents

Syncthing: The File Sync That Never Phones Home

Fifteen years of Dropbox habits, unlearned in an afternoon

Contents

Every file sync product you have used works the same way. Your files go to a company’s servers, the company’s servers send them to your other devices, and you pay the company — in money, in attention, or in the right to scan what you uploaded — for the privilege of being the middle. The architecture is so universal that most people have stopped noticing it is a choice.

Syncthing is the same product with the middle deleted. Your laptop talks to your desktop directly, over an encrypted connection, and no server anywhere holds a copy or knows what you moved. There is no account. There is no sign-up. There is no company that can change the terms, get acquired, or be compelled to hand anything over, because there is nothing to hand over.

I have run it for years across a laptop, a desktop, a phone and a server in a rack, and it is one of the few pieces of self-hosted software I would describe as genuinely boring, which is the highest compliment I have.

How it actually works

Advertisement

Understanding the model prevents most of the confusion people hit.

Devices are identified by keys. When Syncthing starts for the first time it generates a TLS certificate, and the device ID is a hash of the public key — a 63-character string like P56IOI7-MZJNU2Y-.... That ID is the identity. There is no username, no directory, no central registry. Two devices trust each other because you pasted one’s ID into the other, and that mutual introduction is the entire authentication model.

Folders are shared between devices, and each device has a role. A folder can be Send & Receive (the normal case, changes flow both ways), Send Only (this device is the source of truth), or Receive Only (this device accepts changes and never pushes its own). That third one is what makes a rack node a useful sync target.

Discovery is separable from transport. By default Syncthing uses global discovery servers to find your devices’ current addresses, and relay servers to connect them when both sit behind NAT that cannot be traversed. This is the part that alarms privacy-minded people, and the alarm is misplaced: the discovery servers learn a device ID and an IP address, and the relays carry TLS traffic they cannot decrypt. Your files are never readable by any third party at any point. If even that metadata bothers you, turn both off and run it exclusively over your own overlay — a mesh VPN makes every device local to every other, and Syncthing on top of Tailscale needs no discovery infrastructure at all. That is my own setup, and it is strictly better: direct connections, full speed, no third party involved even in metadata.

The sync itself is block-based. Files are split into blocks, hashed, and only changed blocks move. Editing 40 KB of a 2 GB VM image transfers 40 KB-ish rather than 2 GB.

Setting it up properly

Run it as a systemd user service on a desktop and as a system service on a headless box:

1
2
3
# Headless: a dedicated user, and the GUI bound to localhost only
sudo useradd -r -m -d /var/lib/syncthing -s /usr/sbin/nologin syncthing
sudo systemctl enable --now [email protected]

The default GUI listener is 127.0.0.1:8384, and it should stay there. Reach it over an SSH tunnel or through your overlay network with authentication in front. The web GUI has no meaningful protection worth exposing to the internet, and the number of Syncthing instances answering on public IPs is a recurring, dispiriting search result.

1
2
# From your laptop, to reach a headless node's GUI
ssh -L 8384:127.0.0.1:8384 [email protected]

The configuration lives in XML that you can edit directly, and the pieces worth knowing:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<folder id="docs-3f8a2" label="Documents" path="/var/lib/syncthing/Documents"
        type="receiveonly" rescanIntervalS="3600" fsWatcherEnabled="true"
        fsWatcherDelayS="10" ignorePerms="false">
    <device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"/>
    <device id="XY7ABCD-EFGHIJK-LMNOPQR-STUVWXY-Z123456-789ABCD-EFGHIJK-LMNOPQ2"/>
    <minDiskFree unit="%">5</minDiskFree>
    <versioning type="staggered">
        <param key="maxAge" val="2592000"/>
        <param key="cleanoutDays" val="0"/>
    </versioning>
</folder>

Three settings there earn their keep:

fsWatcherEnabled uses inotify so changes propagate in seconds rather than at the next rescan. It is on by default now and worth confirming, because a folder that syncs on an hourly rescan feels broken in a way that is hard to diagnose.

versioning type="staggered" is the one I would make mandatory. It keeps old versions of changed and deleted files on a decaying schedule — hourly for a day, daily for a month, then gone — inside a .stversions directory. Without it, deleting a file on your laptop deletes it everywhere within seconds, which is exactly what you asked for and rarely what you meant.

minDiskFree stops Syncthing filling a disk. A folder that grows past the threshold pauses rather than taking the machine down with it.

Untrusted devices, and the folder you keep at a friend’s house

One feature deserves more attention than it gets. A device can be marked untrusted, which means Syncthing encrypts the folder’s contents with a password before sending, and the remote device stores ciphertext it cannot read. Filenames are encrypted too.

This turns any spare machine anywhere into an off-site replica without a trust relationship. A Pi at a friend’s flat, a VPS, a box at the office — none of them can read a byte, and all of them hold a copy. The password never leaves your trusted devices, so the encryption is genuinely end-to-end rather than a claim on a marketing page.

The caveats are real. The untrusted device cannot be the last surviving copy of anything, because recovering it requires the password and a Syncthing that understands the format. It also cannot run its own backup of the plaintext, obviously. And the feature is more recent than the rest of Syncthing and correspondingly less battle-worn. I use it for one folder, as a third copy behind two boring ones, which is roughly the confidence it has earned.

The turnaround from Dropbox habits

The mental adjustment is the hard part, and it took me a fortnight. Dropbox trains you to think of a folder that exists in a place, with your devices as views onto it. Syncthing has no such place. Every device holds a full, independent copy that happens to agree with the others, and when they disagree the disagreement is a real event with a real winner.

The practical consequences: a device that has been off for a month will take a while to catch up and will resurrect nothing you deleted while it slept, because deletions are recorded rather than inferred. A device with a full disk stops syncing rather than pushing the problem elsewhere. And “is it synced?” becomes a question with a per-device answer instead of a global one.

None of that is difficult. It is different, and expecting it prevents the mild panic of watching a device sit at 84% while you need the file.

The ignore patterns you want immediately

.stignore in the folder root, and getting this right on day one saves you a great deal:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// Never sync these
(?d).DS_Store
(?d)Thumbs.db
(?d)desktop.ini

// Build artefacts and caches  huge, worthless, constantly changing
node_modules
target
__pycache__
.venv
*.pyc

// Anything with an active writer holding a lock
*.sqlite-wal
*.sqlite-shm
.git/index.lock

The (?d) prefix means “delete these if found, and do not treat them as a reason to keep a directory alive”. Syncing node_modules is the classic self-inflicted wound: hundreds of thousands of small files, constantly rewritten, which will make Syncthing look slow while it is in fact doing precisely what you told it to. The general problem is the one in SeaweedFS for absurd amounts of small files — file count is the cost driver, and sync tools feel it worst.

The thing that must be said about backups

Advertisement

Syncthing replicates. Replication propagates your mistakes at wire speed. Delete a directory, rm -rf the wrong path, or let ransomware encrypt your laptop, and every device you sync with faithfully receives that change within seconds. It has done its job perfectly and your data is gone everywhere at once.

This deserves stating plainly because the failure is so tempting: four copies across four machines feels like safety. It is one copy with four viewers. Snapshots are not backups makes the same argument about a different technology, and it applies here with more force, because sync is faster at destroying things than any snapshot schedule is at capturing them.

The arrangement that works: one Syncthing node is Receive Only, lives on a machine your daily driver cannot log into, and has filesystem snapshots underneath it plus a real backup tool pointed at it. Then a restic run from that node to an object store gives you the versioned, off-site, delete-resistant copy Syncthing cannot provide. Borg vs Restic covers the choice; either is right, and having one is what matters. Staggered versioning is a useful safety net for a fat-fingered delete and it is not a backup.

A shape that has worked for years

Concretely, the arrangement I have settled on, offered as a starting point rather than a prescription:

Documents — Send & Receive between laptop, desktop and a rack node. The rack node is Receive Only, so a compromised laptop cannot rewrite history there. Staggered versioning on all three, with a 30-day window.

Photos from the phone — the phone is Send Only into a folder the rack node receives. The phone has no authority to delete anything from the archive, which is what you want when the device most likely to be lost, stolen or wiped is the one holding the originals.

A scratch folder — Send & Receive everywhere, no versioning, aggressively ignored. This is where things live for a week. Treating it as disposable means the rest of the setup stays tidy.

Nothing with a database in it. No Obsidian vault mid-sync while open on two machines, no SQLite file with a live writer, no VM disk that is running. Syncthing will happily sync a file that is being written and the result is a corrupt file replicated perfectly. If a folder has an application holding locks, stop the application or exclude the lock files, and accept that two machines editing the same database simultaneously is a problem no sync tool solves.

That last rule is the one people break, and it accounts for most of the horror stories.

Troubleshooting

Devices see each other but never connect. Check the connection type in the GUI. If it says relay, you have a NAT traversal failure and are running at relay speed, which is deliberately slow. Fix it by opening TCP/UDP 22000 on one end, or by putting both devices on an overlay network where the problem cannot exist.

Sync is stuck at 99% forever. Almost always a file that cannot be written: permissions, a name illegal on the target OS (Windows objects to colons and trailing dots), or a path exceeding a length limit. The folder’s error list names it. ignorePerms helps when syncing between filesystems with incompatible permission models.

Constant conflicts on files nobody edited twice. Look for a program rewriting a file on open — some editors and note apps touch files on load. Also check the clocks: Syncthing uses modification times, and a device with drifting time creates conflicts from nothing. Conflict files are named foo.sync-conflict-20260406-102233-P56IOI7.md, and the device ID in the name tells you which machine lost.

A folder shows “Out of Sync” with 0 items. Usually an ignore-pattern mismatch — one device ignores a file the other is trying to send, so the sender believes it is undelivered forever. .stignore should be identical across devices for the same folder, and this is on you to maintain.

High CPU and RAM on a large folder. Syncthing holds a hash index in memory proportional to file count. Hundreds of thousands of files is heavy, millions is unreasonable. Raise rescanIntervalS and lean on the filesystem watcher rather than periodic scans, and reconsider whether the folder should contain what it contains.

Deleted files keep coming back. One device is Send Only and still holds the file, so it re-sends it. This is the role configuration working correctly and looking haunted.

The verdict

Syncthing is one of the small number of self-hosted tools I would recommend without hedging. It replaces a paid service with something better on nearly every axis — faster on a LAN, no size cap, no account, no scanning, no terms that can change under you — and after setup it is genuinely invisible. Years of running it and the sum of my maintenance has been ignore-pattern edits.

Where it loses honestly: no web interface for your files, so no access from a borrowed machine. No sharing links to send someone a file. Mobile is a compromise, because Android’s background execution rules mean phone sync happens when the OS permits rather than when you want, and iOS support does not meaningfully exist. If you need collaborative editing or public share links, you want Nextcloud, which does far more and demands far more.

For the specific job of keeping your own files identical across your own machines, with nothing in the middle, there is no better option, and the deleted middle is the whole point. Just put a Receive Only node behind a backup before you trust it with anything you would grieve over.

Advertisement
Advertisement
Smarc
Written by Smarc

Founder and editor of vo.rs. A lifelong tinkerer who self-hosts far more than is sensible, hardens Linux boxes for fun, and prods the latest AI tools to see what they can really do. The how-to guides here are the notes Smarc wishes had existed the first time round.