Syncthing on your computers and phones
blog ~23 m
This guide explains how to:
- Install Syncthing on a Windows, macOS or Linux computer
- Install it on an Android or iOS phone
- Pair each device with your always-on hub
- Share folders, and keep the junk out of them
- Handle conflicts and deletions without losing anything
- Stop it eating battery and mobile data
Allow 20–30 minutes per device, plus however long the first sync takes.
This is the client half of the dory build. That guide builds the always-on box the family syncs through. This one is what you do on every laptop, desktop and phone afterwards β and it stands on its own, so if your hub is a NAS, an old ThinkPad in a cupboard or a VPS, the steps below are the same.
Throughout, the hub’s Syncthing daemon is called dorysync and the machine it runs on is
dory.local. Those are two different things: dorysync is the device name you will see in
device lists, set once on the hub in
dory Β§7.3.1
;
dory.local is the hostname you type into a browser or an address field. Substitute your own
names β nothing here depends on those particular strings.
1. What Syncthing is, and what it is not
Syncthing keeps folders identical across your devices. Every device holds a full copy of every folder it shares, and changes propagate directly between devices over encrypted connections. There is no account, no subscription, and no company in the middle holding your files.
β οΈ Important β οΈ: Syncthing is not a backup. It is a replicator. If you delete a photo on your phone, Syncthing does its job and deletes it everywhere else too β quickly and correctly. The same goes for a file mangled by a crashing app, or encrypted by ransomware.
What protects you is file versioning on the hub (Β§7) and a real backup of the hub taken on a schedule. Sync gives you the same files everywhere; backup gives you yesterday’s files. You need both, and they are not the same feature.
The other thing to internalise: two devices only sync while both are awake. A laptop and a phone that are never on at the same time will never exchange a byte. That is the whole reason for an always-on hub.
2. Before you start
You need:
- An always-on peer. Every device pairs with it, and it relays everything by being the one device that is always available. The dory guide builds one on a Raspberry Pi; anything that stays powered will do.
- Its Device ID. A long string like
ABCDEFG-HIJKLMN-..., found on the hub at Actions β Show ID. You will paste it on every device, so put it somewhere you can reach from all of them β a note in your password manager works well. - Admin rights on each computer you are installing on.
You do not need to open any ports on your router for devices that only ever sync at home.
3. Install on a computer
Windows
| |
That installs the core binary. On its own it runs in a console window, which is not what you want on a laptop β most people also install SyncTrayzor, a tray wrapper that starts Syncthing at login, hides the console and gives you a system-tray icon and notifications:
| |
(SyncTrayzor bundles its own copy of Syncthing, so if you install it you can skip the first command. It is a community project, not an official Syncthing release β check https://github.com/canton7/SyncTrayzor for its current state before relying on it.)
macOS
(brew services registers it with launchd so it starts at login and stays running.)
Linux desktop
Use the upstream repo rather than your distro’s package β it is more current and is signed by the project itself:
| |
(That sequence: download the project’s signing key, register a package source that uses it, refresh the catalogue, install.)
Then run it as you, not as root:
| |
(A systemd user service runs under your own account and starts when you log in. On a desktop that is exactly right β Syncthing needs your permissions to touch your files, and no more.)
Open the interface
Whatever the platform, Syncthing’s interface is a web page served locally:
http://127.0.0.1:8384
It is bound to localhost only, so nothing else on the network can reach it. That is the correct default for a laptop β leave it alone. (A hub is the exception, because you need to administer it from elsewhere; that is why the dory guide deliberately changes it.)
4. Install on a phone
Android
β οΈ Important β οΈ: the original Syncthing-Android app is no longer maintained and was removed from the Play Store. Do not go hunting for it.
The maintained community fork is Syncthing-Fork, package
com.github.catfriend1.syncthingfork:
- https://github.com/researchxxl/syncthing-android
- On F-Droid, on the Play Store, and as APKs on the releases page
It is the better app anyway β the run conditions in Β§10 are its headline feature and are what make phone syncing tolerable.
A note on the name, because it looks alarming. You will see this project under two
different GitHub owners: Catfriend1 and researchxxl. That is one account renamed, not
a takeover or a rival fork β both URLs resolve to the same repository under the same owner,
and the app’s package ID still carries the old name. Old links redirect. If you already have
the app installed from either, you are on the right one.
Install it from F-Droid or the Play Store if you can β the store handles updates and signature checks for you, and you can skip the next section entirely.
Sideload only when you need a version the stores do not have yet, which does happen: in
August 2026 the GitHub releases page was on v2.1.3.0 while F-Droid was still serving
2.1.2.0 from a month earlier. If the version you want is on F-Droid, use F-Droid.
F-Droid lists this app as “built and signed by the original developer”, which means its build carries the same signing key as the GitHub APKs, so moving between the two should upgrade cleanly rather than colliding. β οΈ Confirm that on your own phone before relying on it β if an upgrade is ever refused for a signature mismatch, the only route across is to uninstall first, and that deletes the app’s configuration along with it.
On first launch it generates the phone’s Device ID and asks for storage permissions. Grant them; without them it cannot read your camera roll.
Sideloading the APK, without the folklore
Installing an .apk by hand has a reputation for being dangerous magic. It is neither
dangerous nor magic β it is the normal way Android installs software, and the store is just an
app that does it for you. The actual risk is narrow and worth stating plainly: you are
deciding, once, that you trust this file. Everything below is about making that decision on
evidence and then putting the safety catch back on.
Android splits this permission per-app, so what you are about to grant is “let this browser install apps”, not “let anything install anything”.
1. Download the right file
On the phone, open the release page:
https://github.com/researchxxl/syncthing-android/releases
Pick the newest release and download the arm64-v8a APK β that is every Android phone
made in roughly the last decade, and it is the file essentially everyone uses. The plain APK
with no ABI in its name also works but is twice the size, because it contains all four
architectures.
| File | Use it when |
|---|---|
..._arm64-v8a.apk | Normal. Any modern phone. |
..._armeabi-v7a.apk | A genuinely old 32-bit phone |
..._x86.apk / ..._x86_64.apk | An emulator, or a rare x86 tablet |
....apk (no suffix) | You do not know, and do not mind 68 MB |
2. Check you got what they published
Every GitHub release asset has a published SHA-256. If you have the file on a computer, compare:
(The second command asks GitHub what the file should hash to. The two must match.)
Downloading straight to the phone over HTTPS is a reasonable shortcut for a family install β you are trusting the same TLS connection the store uses. Verify the hash when it is worth the effort: a shared family device, or a file that reached you by any route other than github.com.
3. Allow your browser to install, once
The permission lives per-app, and the wording varies slightly by manufacturer:
Settings β Apps β Special app access β Install unknown apps β [your browser] β Allow from this source
Some phones offer the same toggle as a prompt the moment you tap the downloaded file. Taking the prompt is fine β it grants exactly the same thing.
4. Install
Open the downloaded file (Downloads notification, or Files β Downloads) and tap Install.
Play Protect may offer to scan it, or warn that the app is from an unknown developer. Let it scan, and expect the “unknown developer” notice β it means “not signed by a Play-registered developer”, which is true and is not a finding. A red malware warning is different: stop, and check you downloaded from the right place.
5. Confirm it actually worked
Four checks, in order of how much they tell you:
- The app opens and shows its own Device ID.
- Settings β Apps β Syncthing-Fork β App info shows package
com.github.catfriend1.syncthingforkand the version you downloaded. - Pair it with the hub (Β§5) β it reaches Connected.
- A file added on the phone appears on the hub.
Nothing is really proven until 3 and 4.
6. Put the safety catch back on
This is the step everyone forgets, and it is the whole reason sideloading gets its reputation. Go back:
Settings β Apps β Special app access β Install unknown apps β [your browser] β off
The phone is now back to store-only installs. You have lost nothing: the app you installed keeps working, and revoking the permission does not uninstall or restrict it.
β οΈ Leaving that toggle on is the actual risk β not the APK you deliberately chose, but the next thing that talks you into tapping Install six months from now.
Updating later
Sideloaded apps do not auto-update. When a new release appears you repeat steps 1β6.
The reassuring part: Android enforces the signing key on upgrade. An update will only install over the existing app if it was signed by the same key as the version you already have. So the trust decision is the first install; after that the phone refuses anything that is not genuinely from the same source, including a convincing fake. If an update ever fails with a signature error, that is the protection working β do not “fix” it by uninstalling the app first, because that also deletes its configuration.
If you would rather not do this every time, Obtainium watches a GitHub releases page and handles updates for you β at the cost of leaving it holding the install permission. That is a defensible trade for one trusted app, and a worse one if you point it at ten.
iOS
There is no first-party Syncthing app for iOS, and there is unlikely to be one β iOS does not let a third-party app run continuously in the background and reach arbitrary folders, and that is precisely what Syncthing needs.
Your realistic options:
- MΓΆbius Sync β a paid third-party app that embeds Syncthing. It works within the platform’s limits, which means it syncs while it is open or briefly in the background, not continuously. Check its current state and reviews before buying.
- Sync the Mac instead. If your photos already reach a Mac via iCloud or a cable, sync that Mac’s folder and let the iPhone stay out of Syncthing entirely. For most families this is the lower-friction answer.
Be honest with the family about which one you picked. “Your iPhone photos arrive after you open the app” is a fine rule; discovering it by accident three months later is not.
5. Pair with the hub
Every pairing is two-sided: each device has to be told about the other. There is no approve-from-one-end shortcut, and this is deliberate β it is what stops a stranger adding themselves to your folders.
On the new device:
- Add Remote Device.
- Paste the hub’s Device ID.
- Leave the Device Name field blank.
- Save.
On the hub (http://dory.local:8384):
- A notification appears: “Device XXXXXXX wants to connect”. Click Add Device.
- Name it for a human β
hannahs-pixel,bruce-thinkpad. You will be reading this list at 11pm trying to work out which device is stuck; name them properly now. - On the Sharing tab, tick the folders this device should get.
- Save.
Within a minute or so both ends should show Connected.
Why you left the name blank
Devices exchange their configured device name when they connect. Leave the field empty and
the client adopts whatever the hub calls itself β so once connected, the new device’s list
shows dorysync without you typing it, because that is the name set on the hub in
dory Β§7.3.1
. Set it once on the hub, and every device that
ever pairs with it agrees.
Type a name instead and you override that locally, on that one device only. It still works,
but you now maintain the name in as many places as you have devices, and the first
disagreement is a support call β “which one is dory-nas?”
The same applies in reverse: the names you enter on the hub in the list above are the hub’s local labels for each phone and laptop. If you would rather they were consistent everywhere, set the device name on each client (Settings β General β Device Name) and leave the field blank on the hub instead.
β οΈ Names are a convenience, not an identity. The Device ID is what Syncthing actually authenticates β a name is just what gets shown next to it, and either end can call a device whatever it likes.
Introducer β pair once, not fifteen times
With five devices, pairing every device to every other device is fifteen pairings. You do not have to.
On each client, edit the dorysync device and tick Introducer. The hub then introduces
its other devices: when the laptop connects to dorysync, it learns about the phone and the
desktop automatically, and adds them itself.
The result is one pairing per device instead of fifteen, and devices that can still talk to each other directly β faster on the LAN β rather than everything queueing through the hub.
β οΈ Only tick Introducer on a device you fully control. It means “add whoever this device vouches for”, which is correct for your own hub and wrong for a friend’s.
6. Finding the hub β discovery
Most of the time this section is not needed: on a home network Syncthing finds its peers by
local discovery, a broadcast on the LAN. You paste a Device ID, and the address sorts
itself out. The address field stays on dynamic and that is the right answer.
When it does not connect, the usual causes are:
- Guest WiFi or AP isolation β the access point deliberately blocks device-to-device traffic. Very common, and easy to miss because the internet works fine.
- Separate VLANs or SSIDs for IoT and main devices, with no broadcast between them.
- A router that drops broadcast traffic, or a mesh system that does the same between nodes.
The fix is to stop relying on discovery and tell the client exactly where the hub is. Edit
the dorysync device β Addresses β replace dynamic with:
tcp://dory.local:22000
If mDNS is also unavailable β some networks do not resolve .local names either β use the
hub’s IP address instead, and give it a DHCP reservation on your router so it stops moving:
tcp://192.168.1.42:22000
(Port 22000 is Syncthing’s data port, and is not the same as 8384, which is only the web interface. You are giving the client a route to the hub, not exposing anything new.)
Away from home
Two more mechanisms cover devices that leave the house:
- Global discovery β devices announce themselves to Syncthing’s public discovery servers so peers can find each other across the internet. It publishes your Device ID and IP to those servers; a Device ID is not a secret, but it is not nothing either.
- Relays β when neither device can reach the other directly, traffic is bounced through a volunteer-run relay. The contents stay encrypted end-to-end, so a relay operator cannot read your files, but it is slow β expect a fraction of your normal speed.
Both are on by default. If every device only ever syncs at home, you can turn both off in Settings β Connections and lose nothing. If a laptop travels, leave them on and accept that a big sync away from home will crawl.
7. Share a folder
The rule that decides everything
β οΈ Important β οΈ: a Syncthing folder is shared whole. Every device you share it with gets the entire tree. There is no way to share only a subdirectory with a particular device.
This surprises people, because it means you cannot have one big folder called Computers on
the hub and give each laptop “its bit”. Share that folder with two laptops and each one
downloads the other’s files. The unit of sharing is one folder per device, per directory
that device syncs.
Three fields, and only one of them has to match
| Field | Scope | Rule |
|---|---|---|
| Folder ID | Cluster-wide | Must match exactly on your device and the hub. This is what makes two folders “the same folder”. |
| Folder Label | Per device | Cosmetic. Call it whatever you like locally. |
| Path | Per device | Yours to choose. It has nothing to do with the hub’s path. |
So there is no mapping to configure and no table to keep in step. You and the hub agree on one string β the Folder ID β and each end independently decides where the files live.
Worked example
The hub keeps the family tidy by nesting device directories under a class
(computers/, phones/). You never see that, and you do not have to reproduce it. For a
laptop called dinolappy syncing its presentations:
| On your laptop | On the hub | |
|---|---|---|
| Folder ID | dinolappy-presentations | dinolappy-presentations β identical |
| Label | Presentations | dinolappy presentations |
| Path | ~/Presentations | /mnt/raid/family-data/computers/dinolappy/presentations |
Your ~/Presentations becomes β¦/computers/dinolappy/presentations on the hub because the
hub was configured with that path, not because of anything you enter. If your hub is the
dory
build, Β§7.4 there sets those paths up.
What you actually do
- Add Folder.
- Set the Folder ID to the string whoever runs the hub gave you. Get this exactly right, including case and hyphens β a typo produces a brand-new folder that syncs with nothing, and the symptom is simply that nothing ever happens.
- Set the path to wherever you want the files locally.
- On the Sharing tab, tick
dorysync. - Save. The hub accepts, and the folder starts syncing.
β οΈ A Folder ID cannot be changed after the fact. Getting it wrong means removing the folder and adding it again β so check it before you save, not after the first sync.
Asking for a new folder
You do not create folders on the hub yourself β whoever administers it does, so that Folder IDs and paths stay consistent instead of fifteen people inventing their own. The routine is:
- You ask, saying which device owns the files, what the folder is for in one word, and roughly how big it is.
- The admin creates it on the hub and shares it with your device only.
- They send you the Folder ID. That one string is the entire handover.
- You accept it with the four steps above, choosing your own local path.
The full version, including the admin’s side, is dory Β§7.6 β Adding a folder later .
Choosing a path
| Platform | A sensible path |
|---|---|
| Linux / macOS | ~/Presentations or ~/Sync/presentations |
| Windows | C:\Users\<you>\Presentations |
| Android | Use the app’s folder picker, not a typed path |
β οΈ Android storage β οΈ: modern Android restricts which directories an app may write to.
Always pick the folder through Syncthing-Fork’s own picker rather than typing a path β a path
that looks right can silently fail to sync, or sync read-only. Syncing the camera roll
(DCIM) generally works; syncing arbitrary paths on the SD card often does not.
Folder type
Each device chooses how it participates:
- Send & Receive β the default. Changes flow both ways.
- Send Only β this device publishes changes but never accepts them. Right for a phone’s camera roll: photos go up, and nothing on the hub can delete them from the phone.
- Receive Only β accepts changes but never sends. Right for a hub folder you want to be a faithful mirror, and for a device you do not trust to make edits.
Versioning
On the hub, set versioning on every shared folder: edit the folder β File Versioning β Staggered, with a versions path and a max age of a year.
This is what turns “someone deleted it on their phone” from a disaster into an inconvenience. Staggered versioning keeps many versions of recent files and progressively fewer old ones, so the space cost stays bounded. Set it on the hub, where there is disk; leave it off on phones, where there is not.
Reference: https://docs.syncthing.net/users/versioning.html
8. Ignore patterns
By default Syncthing syncs everything in a folder, including a great deal you do not want: build artefacts, caches, thumbnail databases and OS droppings. On a phone that is battery and mobile data spent on nothing.
Edit a folder β Ignore Patterns, and add:
// OS droppings
.DS_Store
._*
Thumbs.db
desktop.ini
// caches and build output
node_modules
.venv
__pycache__
target
*.tmp
~$*
// don't sync Syncthing's own versions folder
.stversions
Notes that save time later:
- The patterns live in a
.stignorefile at the root of the folder. It is not synced by default, so each device has its own β set it on every device, or add#includeto share one. - Lines starting
//are comments. - A leading
!negates:!important.tmpkeeps that one file despite*.tmpabove it. Order matters β the first matching line wins. - Ignoring a file that is already synced does not delete it elsewhere; it just stops tracking changes to it.
9. Conflicts, deletions and versioning
Conflicts
Edit the same file on two devices before they sync, and Syncthing cannot know which you meant. It keeps both: the one that arrives second is renamed
notes.sync-conflict-20260907-142233-ABCDEFG.md
β date, time, and the Device ID of the device that made the losing edit. Nothing is lost, but nothing is resolved either. Open both, merge by hand, delete the conflict file.
If you see conflicts constantly, the cause is almost always a file that several devices write without coordinating β a notes app’s database, a password vault, a running VM disk. Move it out of Syncthing, or share it Send Only from exactly one device.
β οΈ Never sync a live database or VM image. Syncthing copies files, not transactions, and will happily replicate a half-written database. That is how corruption spreads to every device at once.
Deletions
Deleting a file deletes it everywhere within seconds. On the hub, versioning (Β§7) keeps a copy
at the versions path β usually .stversions inside the folder β so recovery means finding the
file there and moving it back.
On devices without versioning, the file is simply gone. This is the single most important thing to tell the rest of the family: the shared folder is not a bin you can rummage in.
10. Keeping it quiet
Left at its defaults on a phone, Syncthing will sync a holiday’s worth of photos over 4G at an airport, and wake the hub’s drives every time someone takes a picture. Both are fixable.
On Android β run conditions
Syncthing-Fork can hold sync until conditions are met. The setting is Run conditions, and the combination worth starting from is:
- Run only while charging
- Run only on WiFi, restricted to your home network’s SSID
- Optionally, Run only during a time window such as 01:00β06:00
Phones charge overnight on home WiFi. That one combination gives you a nightly sync window with no server-side scheduling at all, and stops the array being woken every time someone takes a photo in the park.
Mobile data
If you skip the WiFi restriction, at minimum mark mobile connections as metered in Settings β Connections and set a rate limit. A first sync of a phone full of photos is tens of gigabytes; over a metered connection that is an expensive surprise.
On computers
Less critical, but two settings earn their keep on a laptop:
- Rate limits (Settings β Connections) so a big sync does not saturate the uplink during a video call.
- Pause on metered connection, for tethering.
The first sync
Say this out loud to whoever owns the phone: the first sync can take hours. Thousands of photos over WiFi is genuinely slow, and it looks broken while it is working. Start it in the evening, plugged in, and check it in the morning.
11. When something is wrong
| Symptom | First place to look |
|---|---|
| Device stuck on Disconnected | Is the other device actually awake? Both ends must have added each other (Β§5) |
| Never connects at home | Local discovery blocked β add a static address (Β§6) |
| Connects only via Relay, slowly | Same cause; a static address on the LAN fixes the speed |
Please increase inotify limits (Linux only) | The kernel’s per-user watch limit, default 8192, is too low for a big folder β see below |
| Folder added, but nothing ever syncs | Folder ID does not match the hub’s, character for character (Β§7) β check case and hyphens |
| Hub shows a folder you did not expect | Someone typo’d a Folder ID and created a new one; fix the ID on the client and delete the stray |
| Out of Sync and staying there | Open the folder β Failed Items; usually permissions or a filename the OS rejects |
| Android syncs nothing | Storage permission denied, or a typed path instead of the folder picker (Β§7) |
| Android syncs only when open | Battery optimisation is killing it β exclude Syncthing in Android’s battery settings |
Constant .sync-conflict-* files | A file being written by several devices β stop syncing it (Β§9) |
| A file will not sync, no error | Check the ignore patterns on both ends (Β§8) |
config.xml “not found” | It moved to ~/.local/state/syncthing/config.xml in v1.27 β run syncthing --paths to ask, or use syncthing cli |
| Web interface will not open | Is the service running? systemctl --user status syncthing, or check the tray icon |
inotify limits, on Linux
Syncthing watches the filesystem rather than re-reading it on a timer. On Linux that uses inotify, and the kernel caps how many directories one user may watch β typically 8192, which a large folder exceeds. Windows and macOS have no equivalent limit, so this is a Linux problem only.
(204800 is Syncthing’s own recommended value. sysctl --system applies it immediately β
restarting Syncthing is enough, and no reboot is needed. Upstream’s FAQ says to reboot because
it documents appending to /etc/sysctl.conf instead of using a drop-in file.)
Until you do this the watcher is not running, and changes are only noticed by the periodic scan β so edits can take an hour to propagate and it looks like Syncthing is simply slow.
Reference: https://docs.syncthing.net/users/faq.html#inotify-limits
The config file
Older guides tell you to edit ~/.config/syncthing/config.xml directly.
As of Syncthing 1.27 the config moved to the XDG state directory, so that path no longer
exists on a fresh install. Never guess it β syncthing --paths prints the real locations.
Better still, use the syncthing cli commands, which talk to the running daemon through its
API so the file is written in a form Syncthing agrees with, rather than patched behind its
back.
12. References
- Syncthing documentation β https://docs.syncthing.net/
- Getting started β https://docs.syncthing.net/intro/getting-started.html
- Ignore patterns β https://docs.syncthing.net/users/ignoring.html
- File versioning β https://docs.syncthing.net/users/versioning.html
- Firewall and ports β https://docs.syncthing.net/users/firewall.html
- Debian/Ubuntu apt repo β https://apt.syncthing.net/
- Syncthing-Fork for Android β
https://github.com/researchxxl/syncthing-android
(formerly
Catfriend1/syncthing-android; the old URL redirects) - Android “install unknown apps” β https://support.google.com/android/answer/12623953
- SyncTrayzor for Windows β https://github.com/canton7/SyncTrayzor
- Building the hub β dory, a small homelab NAS