1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
|
.\" Man page generated from reStructuredText.
.
.
.nr rst2man-indent-level 0
.
.de1 rstReportMargin
\\$1 \\n[an-margin]
level \\n[rst2man-indent-level]
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
-
\\n[rst2man-indent0]
\\n[rst2man-indent1]
\\n[rst2man-indent2]
..
.de1 INDENT
.\" .rstReportMargin pre:
. RS \\$1
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
. nr rst2man-indent-level +1
.\" .rstReportMargin post:
..
.de UNINDENT
. RE
.\" indent \\n[an-margin]
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
.nr rst2man-indent-level -1
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-VERSIONING" "7" "Nov 22, 2023" "v1.26.0" "Syncthing"
.SH NAME
syncthing-versioning \- Keep automatic backups of deleted files by other nodes
.sp
Syncthing supports archiving the old version of a file when it is deleted or
replaced with a newer version from the cluster. This is called “file
versioning” and uses one of the available \fIversioning strategies\fP described
below. File versioning is configured per folder, on a per\-device basis, and
defaults to “no file versioning”, i.e. no old copies of files are kept.
.sp
\fBNOTE:\fP
.INDENT 0.0
.INDENT 3.5
Versioning applies to changes received \fIfrom other devices\fP\&. That is, if
Alice has versioning turned on and Bob changes a file, the old version
will be archived on Alice’s computer when that change is synced from
Bob. If Alice changes a file locally on her own computer Syncthing will
not and can not archive the old version.
.UNINDENT
.UNINDENT
.sp
The applicable configuration options for each versioning strategy are described
below. For most of them it’s possible to specify where the versions are stored,
with the default being the \fB\&.stversions\fP folder inside the shared folder path.
If you set a custom version path, please ensure that it’s on the same partition
or filesystem as the regular folder path, as moving files there may otherwise
fail.
.SH TRASH CAN FILE VERSIONING
.sp
This versioning strategy emulates the common “trash can” approach. When a file
is deleted or replaced due to a change on a remote device, it is moved to
the trash can in the \fB\&.stversions\fP folder. If a file with the same name was
already in the trash can it is replaced.
.sp
A \fI\%configuration option\fP is
available to clean the trash can from files older than a specified number of
days. If this is set to a positive number of days, files will be removed when
they have been in the trash can that long. Setting this to zero prevents any
files from being removed from the trash can automatically.
.SH SIMPLE FILE VERSIONING
.sp
With “Simple File Versioning” files are moved to the \fB\&.stversions\fP folder when
replaced or deleted on a remote device. In addition to the
\fI\%cleanoutDays\fP option, this strategy also takes a
value in an input titled “Keep Versions” which tells Syncthing how many old
versions of the file it should \fI\%keep\fP\&. For
example, if you set this value to 5, if a file is replaced 5 times on a remote
device, you will see 5 time\-stamped versions on that file in the \fB\&.stversions\fP
folder on the other devices sharing the same folder.
.SH STAGGERED FILE VERSIONING
.sp
With “Staggered File Versioning” files are also moved to the \fB\&.stversions\fP
folder when replaced or deleted on a remote device (just like “Simple File
Versioning”), however, versions are automatically deleted if they are older than
the maximum age or exceed the number of files allowed in an interval.
.sp
The following intervals are used and they each have a maximum number of files
that will be kept for each.
.INDENT 0.0
.TP
.B 1 Hour
For the first hour, the oldest version in every 30\-seconds interval is
kept.
.TP
.B 1 Day
For the first day, the oldest version in every hour is kept.
.TP
.B 30 Days
For the first 30 days, the oldest version in every day is kept.
.TP
.B Until Maximum Age
Until maximum age, the oldest version in every week is kept.
.TP
.B Maximum Age
The maximum time to keep a version in days. For example, to keep replaced or
deleted files in the \fB\&.stversions\fP folder for an entire year, use 365. If
only for 10 days, use 10. Corresponds to the
\fI\%maxAge\fP option.
\fBNote: Set to 0 to keep versions forever.\fP
.UNINDENT
.sp
This means that there is only one version in each interval and as files age they
will be deleted unless when the interval they are entering is empty. By keeping
the oldest versions this versioning scheme preserves the file if it is
overwritten.
.sp
For more info, check the \fI\%unit test file\fP <\fBhttps://github.com/syncthing/syncthing/blob/main/lib/versioner/staggered_test.go#L32\fP>
that shows which versions are deleted for a specific run.
.SH EXTERNAL FILE VERSIONING
.sp
This versioning strategy delegates the decision on what to do to an
\fI\%external command\fP (e.g. a program or a
command line script). Just prior to a file being replaced, the command will be
executed. The file needs to be removed from the folder in the process, or
otherwise Syncthing will report an error. The command can use the following
templated arguments:
.INDENT 0.0
.TP
.B %FOLDER_PATH%
Path to the folder
.TP
.B %FILE_PATH%
Path to the file within the folder
.UNINDENT
.sp
Note that the former expands to the path of the actual Syncthing folder,
and the latter to the path inside that folder. For instance, if you use
the default \fBSync\fP folder in Windows, and the full path to the file is
\fBC:\eUsers\eUser\eSync\eFamily photos\eIMG_2021\-03\-01.jpg\fP, then the
\fB%FOLDER_PATH%\fP will be \fBC:\eUsers\eUser\eSync\fP, and the
\fB%FILE_PATH%\fP will be \fBFamily photos\eIMG_2021\-03\-01.jpg\fP\&.
.SS Example for Unixes
.sp
Let’s say I want to keep the latest version of each file as they are replaced
or removed; essentially I want a “trash can”\-like behavior. For this, I create
the following script and store it as \fB/Users/jb/bin/onlylatest.sh\fP (i.e. the
\fBbin\fP directory in my home directory):
.INDENT 0.0
.INDENT 3.5
.sp
.nf
.ft C
#!/bin/sh
set \-eu
# Where I want my versions stored
versionspath=~/.trashcan
# The parameters we get from Syncthing
folderpath=\(dq$1\(dq
filepath=\(dq$2\(dq
# First ensure the dir where we need to store the file exists
outpath=$(dirname \(dq$versionspath/$filepath\(dq)
mkdir \-p \(dq$outpath\(dq
# Then move the file there
mv \-f \(dq$folderpath/$filepath\(dq \(dq$versionspath/$filepath\(dq
.ft P
.fi
.UNINDENT
.UNINDENT
.sp
I must ensure that the script has execute permissions (\fBchmod 755
onlylatest.sh\fP), then configure Syncthing with command \fB/Users/jb/bin/onlylatest.sh %FOLDER_PATH% %FILE_PATH%\fP
.sp
Let’s assume I have a folder “default” in ~/Sync, and that within that folder
there is a file \fBdocs/letter.txt\fP that is being replaced or deleted. The
script will be called as if I ran this from the command line:
.INDENT 0.0
.INDENT 3.5
.sp
.nf
.ft C
$ /Users/jb/bin/onlylatest.sh /Users/jb/Sync docs/letter.txt
.ft P
.fi
.UNINDENT
.UNINDENT
.sp
The script will then move the file in question to
\fB~/.trashcan/docs/letter.txt\fP, replacing any previous version of that letter
that may already have been there.
.SS Examples for Windows
.SS Move to a given folder using the command prompt (CMD)
.sp
On Windows we can use a batch script to perform the same “trash can”\-like
behavior as mentioned above. I created the following script and saved it as
\fBC:\eUsers\emfrnd\eScripts\eonlylatest.bat\fP\&.
.INDENT 0.0
.INDENT 3.5
.sp
.nf
.ft C
@echo off
rem Enable UTF\-8 encoding to deal with multilingual folder and file names
chcp 65001
rem We need command extensions for md to create intermediate folders in one go
setlocal enableextensions
rem Where I want my versions stored
set \(dqversions_path=%USERPROFILE%\e.trashcan\(dq
rem The parameters we get from Syncthing, \(aq~\(aq removes quotes if any
set \(dqfolder_path=%~1\(dq
set \(dqfile_path=%~2\(dq
rem First ensure the dir where we need to store the file exists
for %%f in (\(dq%versions_path%\e%file_path%\(dq) do set \(dqoutput_path=%%~dpf\(dq
if not exist \(dq%output_path%\(dq md \(dq%output_path%\(dq || exit /b
rem Finally move the file, overwrite existing file if any
move /y \(dq%folder_path%\e%file_path%\(dq \(dq%versions_path%\e%file_path%\(dq
.ft P
.fi
.UNINDENT
.UNINDENT
.sp
Finally, I set \fB\(dqC:\eUsers\emfrnd\eScripts\eonlylatest.bat\(dq \(dq%FOLDER_PATH%\(dq
\(dq%FILE_PATH%\(dq\fP as the command name in Syncthing.
.SS Move to the Recycle Bin using PowerShell
.sp
We can use PowerShell to send files directly to the Recycle Bin, which
mimics the behaviour of deleting them using the Windows Explorer.
Firstly, create the following script and save it in your preferred
location, e.g. \fBC:\eUsers\eUser\eScripts\eSendToRecycleBin.ps1\fP\&.
.INDENT 0.0
.INDENT 3.5
.sp
.nf
.ft C
# PowerShell has no native method to recycle files, so we use Visual
# Basic to perform the operation. If succeeded, we also include the
# recycled file in the Syncthing\(aqs DEBUG output.
Add\-Type \-AssemblyName Microsoft.VisualBasic
[Microsoft.VisualBasic.FileIO.FileSystem]::DeleteFile($args,\(aqOnlyErrorDialogs\(aq,\(aqSendToRecycleBin\(aq)
if ($?) {
Write\-Output (\(dqRecycled \(dq + $args + \(dq.\(dq)
}
.ft P
.fi
.UNINDENT
.UNINDENT
.sp
Alternatively, the script can be expanded to send only deleted files to
the Recycle Bin, and permanently delete modified ones, which makes it
more consistent with how the Explorer works.
.INDENT 0.0
.INDENT 3.5
.sp
.nf
.ft C
# PowerShell has no native method to recycle files, so we use Visual
# Basic to perform the operation.
Add\-Type \-AssemblyName Microsoft.VisualBasic
# We need to test if a Syncthing .tmp file exists. If it does, we assume
# a modification and delete the existing file. If if does not, we assume
# a deletion and recycle the current file. If succeeded, we also include
# the deleted/recycled file in the Syncthing\(aqs DEBUG output.
if (Test\-Path \-LiteralPath ((Split\-Path \-Path $args) + \(dq\e~syncthing~\(dq + (Split\-Path \-Path $args \-Leaf) + \(dq.tmp\(dq)) {
[Microsoft.VisualBasic.FileIO.FileSystem]::DeleteFile($args,\(aqOnlyErrorDialogs\(aq,\(aqDeletePermanently\(aq)
if ($?) {
Write\-Output (\(dqDeleted \(dq + $args + \(dq.\(dq)
}
} else {
[Microsoft.VisualBasic.FileIO.FileSystem]::DeleteFile($args,\(aqOnlyErrorDialogs\(aq,\(aqSendToRecycleBin\(aq)
if ($?) {
Write\-Output (\(dqRecycled \(dq + $args + \(dq.\(dq)
}
}
.ft P
.fi
.UNINDENT
.UNINDENT
.sp
Finally, we set the command name in Syncthing to \fBpowershell.exe
\-ExecutionPolicy Bypass \-File \(dqC:\eUsers\eUser\eScripts\eSendToRecycleBin.ps1\(dq
\(dq%FOLDER_PATH%\e%FILE_PATH%\(dq\fP\&.
.sp
The only caveat that you should be aware of is that if your Syncthing
folder is located on a portable storage, such as a USB stick, or if you
have the Recycle Bin disabled, then the script will end up deleting all
files permanently.
.SH CONFIGURATION PARAMETER REFERENCE
.sp
The versioning settings are grouped into their own section of each folder in the
\fI\%configuration file\fP\&. The following shows an
example of such a section in the XML:
.INDENT 0.0
.INDENT 3.5
.sp
.nf
.ft C
<folder id=\(dq...\(dq>
<versioning type=\(dqsimple\(dq>
<cleanupIntervalS>3600</cleanupIntervalS>
<fsPath></fsPath>
<fsType>basic</fsType>
<param key=\(dqcleanoutDays\(dq val=\(dq0\(dq></param>
<param key=\(dqkeep\(dq val=\(dq5\(dq></param>
</versioning>
</folder>
.ft P
.fi
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
.B versioning.type
Selects one of the versioning strategies: \fBtrashcan\fP, \fBsimple\fP,
\fBstaggered\fP, \fBexternal\fP or leave empty to disable versioning completely.
.UNINDENT
.INDENT 0.0
.TP
.B versioning.fsPath
Overrides the path where old versions of files are stored and defaults to
\fB\&.stversions\fP if left empty. An absolute or relative path can be
specified. The latter is interpreted relative to the shared folder path, if
the \fI\%fsType\fP is configured as \fBbasic\fP\&. Ignored
for the \fBexternal\fP versioning strategy.
.sp
This option used to be stored under the keys \fBfsPath\fP or \fBversionsPath\fP
in the \fI\%params\fP element.
.UNINDENT
.INDENT 0.0
.TP
.B versioning.fsType
The internal file system implementation used to access this versions folder.
Only applies if \fI\%fsPath\fP is also set non\-empty,
otherwise the \fI\%filesystemType\fP from the folder element is used
instead. Refer to that option description for possible values. Ignored for
the \fBexternal\fP versioning strategy.
.sp
This option used to be stored under the key \fBfsType\fP in the
\fI\%params\fP element.
.UNINDENT
.INDENT 0.0
.TP
.B versioning.cleanupIntervalS
The interval, in seconds, for running cleanup in the versions folder. Zero
to disable periodic cleaning. Limited to one year (31536000 seconds).
Ignored for the \fBexternal\fP versioning strategy.
.sp
This option used to be stored under the key \fBcleanInterval\fP in the
\fI\%params\fP element.
.UNINDENT
.INDENT 0.0
.TP
.B versioning.params
Each versioning strategy can have configuration parameters specific to its
implementation under this element.
.UNINDENT
.INDENT 0.0
.TP
.B versioning.params.cleanoutDays
The number of days to keep files in the versions folder. Zero means to keep
forever. Older elements encountered during cleanup are removed.
.UNINDENT
.INDENT 0.0
.TP
.B versioning.params.keep
The number of old versions to keep, per file.
.UNINDENT
.INDENT 0.0
.TP
.B versioning.params.maxAge
The maximum time to keep a version, in seconds. Zero means to keep forever.
.UNINDENT
.INDENT 0.0
.TP
.B versioning.params.command
External command to execute for storing a file version about to be replaced
or deleted. If the path to the application contains spaces, it should be
quoted.
.UNINDENT
.SH AUTHOR
The Syncthing Authors
.SH COPYRIGHT
2014-2019, The Syncthing Authors
.\" Generated by docutils manpage writer.
.
|