Syncthing is great, and mostly Just Werks, but some things about it aren’t entirely obvious.
Its unit of synchronization is a folder. Everything inside the folder gets synced to the equivalent folder on the other devices you choose to share it with. The other devices don’t have to name the folder the same way or put it in the same place on their filesystems, but the contents will still be mirrored.
Synced folders can’t be nested. That is, if you have a folder
~/docs
that is a synced, you can’t have a folder inside it
like ~/docs/work
that is synced in some different way
(e.g. to different devices or with different settings).
The solution is symlinks. Put your synced folders all in one place. I
put mine in a folder ~/st
, in a flat structure like
this:
~/st/me
~/st/camera-sync
~/st/music
~/st/notes
~/st/film-and-tv
Then I put symlinks to those where I actually want them on my filesystem:
~/me -> ~/st/me
~/me/pics/camera-sync -> ~/st/camera-sync
~/me/music -> ~/st/music
~/me/docs/notes -> ~/st/notes
~/me/film-and-tv -> ~/st/film-and-tv
This way, I have granular control over what gets synced to where,
while still having my files structured how I like. My phone has
music
, notes
, and camera-sync
,
but it doesn’t get everything else in ~/me
. My desktop has
a bigger hard drive, so it syncs the large film-and-tv
folder to my backup machine, but it doesn’t sync to my laptop or my
phone.
On a machine where an “outer” folder is synced, but a “nested” folder
isn’t, you’ll have a dead symlink. My laptop has a
~/me/film-and-tv
symlink that points to a nonexistent
~/st/film-and-tv
. You might find this annoying but I like
the explicitness of it.
By the way, I don’t sync my entire home directory. So many programs
have a habit of puking dotfiles and all kinds of other junk into the
root of ~
, stuff that I don’t want backed up or mirrored
onto other machines. I put all the stuff I actually care about into
~/me
, then symlink it to where I need. e.g. config I care
about lives in ~/me/dotfiles
then I manually put symlinks
in ~/.config
to point to them. You can use GNU stow to
automate this but I’ve never gotten around to doing it.
There is support for a .stignore
file to prevent syncing
of certain files (similar syntax as .gitignore
), but the
.stignore
file itself doesn’t get synced. There’s
a good
reason for this, but it’s still an annoying compromise. If you need
to share ignore lists across devices, you need to use a
#include
directive at the top of the ignorefile, like
#include .stglobalignore
, where
.stglobalignore
is a file that does get synced. I used this
as a starting point. So then you need to manually put a
.stignore
file with the contents
#include .stglobalignore
into the root of each device’s sync folder.
Then if you want, you can put folder-specific ignores in another included file:
#include .stglobalignore
#include .stmeignore
One place where syncthing kinda falls over is in the handling of git
repositories, and I’m not sure if it’s fixable given its design. tldr
synchronizing a file is atomic but synchronizing a directory isn’t. Git
repositories are basically databases implemented the old fashioned way,
on the file system. The git
program will get confused and
upset if another program moves/replaces/deletes files in the
.git
repo while it’s in the middle of doing an operation
like a commit. So the .git
folder can get corrupted. AFAIK
there isn’t really a way around this aside from ignoring
.git
folders entirely.
But that leads to another annoyance, which is that even though the
.git
folder is ignored, the working directory it belongs to
isn’t. There isn’t a way to tell Syncthing to ignore a folder based on
its contents rather than its name. So you can end up with your working
directories synced but the underlying git repo not getting synced, which
can be confusing.
What I end up doing is to put all my repositories into
~/me/projects
, and put that whole folder in the ignore
list. But I don’t find that a completely satisfactory solution because
it means my most interesting files aren’t actually synced across
devices. I often forget to push to remote, or I don’t bother to set up a
remote repo in the first place. ¯\_(ツ)_/¯ I need to figure out a better
solution here.