syncthing-bep

package: syncthing

title: syncthing-bep(7)

summary: Block Exchange Protocol v1

text:
# syncthing-bep(7)

## NAME
syncthing-bep - Block Exchange Protocol v1

## INTRODUCTION AND DEFINITIONS
The Block Exchange Protocol (BEP) is used between two or more devices thus forming a cluster. Each device has one or more folders of files described by the local model, containing metadata and block hashes. The local model is sent to the other devices in the cluster. The union of all files in the local models, with files selected for highest change version, forms the global model. Each device strives to get its folders in sync with the global model by requesting missing or outdated blocks from the other devices in the cluster.

File data is described and transferred in units of blocks, each being from 128 KiB (131072 bytes) to 16 MiB in size, in steps of powers of two. The block size may vary between files but is constant in any given file, except for the last block which may be smaller.

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 <https://datatracker.ietf.org/doc/html/rfc2119.html>.

## TRANSPORT AND AUTHENTICATION
BEP is deployed as the highest level in a protocol stack, with the lower level protocols providing encryption and authentication.

```
+-----------------------------+
|   Block Exchange Protocol   |
|-----------------------------|
| Encryption & Auth (TLS 1.3) |
|-----------------------------|
|      Reliable Transport     |
|-----------------------------|
v             ...             v
```

The encryption and authentication layer SHALL use TLS 1.3 or a higher revision.

The exact nature of the authentication is up to the application, however it SHALL be based on the TLS certificate presented at the start of the connection. Possibilities include certificates signed by a common trusted CA, preshared certificates, preshared certificate fingerprints or certificate pinning combined with some out of band first verification. The reference implementation uses preshared certificate fingerprints (SHA-256) referred to as “Device IDs”.

There is no required order or synchronization among BEP messages except as noted per message type - any message type may be sent at any time and the sender need not await a response to one message before sending another.

The underlying transport protocol MUST guarantee reliable packet delivery.

In this document, in diagrams and text, “bit 0” refers to the most significant bit of a word; “bit 15” is thus the least significant bit of a 16 bit word (int16) and “bit 31” is the least significant bit of a 32 bit word (int32). Non protocol buffer integers are always represented in network byte order (i.e., big endian) and are signed unless stated otherwise, but when describing message lengths negative values do not make sense and the most significant bit MUST be zero.

The protocol buffer schemas in this document are in proto3 syntax. This means, among other things, that all fields are optional and will assume their default value when missing. This does not necessarily mean that a message is valid with all fields empty - for example, an index entry for a file that does not have a name is not useful and MAY be rejected by the implementation. However the folder label is for human consumption only so an empty label should be accepted - the implementation will have to choose some way to represent the folder, perhaps by using the ID in it’s place or automatically generating a label.

## PRE-AUTHENTICATION MESSAGES
AFTER establishing a connection, but BEFORE performing any authentication, devices MUST exchange Hello messages.

Hello messages are used to carry additional information about the peer, which might be of interest to the user even if the peer is not permitted to communicate due to failing authentication. Note that the certificate based authentication may be considered part of the TLS handshake that precedes the Hello message exchange, but even in the case that a connection is rejected a Hello message must be sent before the connection is terminated.

Hello messages MUST be prefixed with an int32 containing the magic number 0x2EA7D90B, followed by an int16 representing the size of the message, followed by the contents of the Hello message itself.

```
 0                   1

 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|             Magic             |
|           (32 bits)           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|             Length            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/                               /
\             Hello             \
/                               /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
```

The Hello message itself is in protocol buffer format with the following schema:

```
message Hello {

    string device_name    = 1;

    string client_name    = 2;

    string client_version = 3;
}
```

### Fields (Hello message)
The device_name is a human readable (configured or auto detected) device name or host name, for the remote device.

The client_name and client_version identifies the implementation. The values SHOULD be simple strings identifying the implementation name, as a user would expect to see it, and the version string in the same manner. An example client name is “syncthing” and an example client version is “v0.7.2”. The client version field SHOULD follow the patterns laid out in the Semantic Versioning <https://semver.org/> standard.

Immediately after exchanging Hello messages, the connection MUST be dropped if the remote device does not pass authentication.

## POST-AUTHENTICATION MESSAGES
Every message post authentication is made up of several parts:

- A header length word

- A Header

- A message length word

- A Message

```
 0                   1

 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|         Header Length         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/                               /
\            Header             \
/                               /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|         Message Length        |
|           (32 bits)           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/                               /
\            Message            \
/                               /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
```

The header length word is 16 bits. It indicates the length of the following Header message. The Header is in protocol buffer format. The Header describes the type and compression status of the following message.

The message is preceded by the 32 bit message length word and is one of the concrete BEP messages described below, identified by the type field of the Header.

As always, the length words are in network byte order (big endian).

```
message Header {

    MessageType        type        = 1;

    MessageCompression compression = 2;
}
enum MessageType {

    CLUSTER_CONFIG    = 0;

    INDEX             = 1;

    INDEX_UPDATE      = 2;

    REQUEST           = 3;

    RESPONSE          = 4;

    DOWNLOAD_PROGRESS = 5;

    PING              = 6;

    CLOSE             = 7;
}
enum MessageCompression {

    NONE = 0;

    LZ4  = 1;
}
```

When the compression field is NONE, the message is directly in protocol buffer format.

When the compression field is LZ4, the message consists of a 32 bit integer describing the uncompressed message length followed by a single LZ4 block. After decompressing the LZ4 block it should be interpreted as a protocol buffer message just as in the uncompressed case.

## MESSAGE SUBTYPES

### Cluster Config
This informational message provides information about the cluster configuration as it pertains to the current connection. A Cluster Config message MUST be the first post authentication message sent on a BEP connection. Additional Cluster Config messages MAY be sent after the initial exchange to change the connection in place with the update configuration. If an implementation does not support that, it SHOULD close the connection.

### Protocol Buffer Schema

```
message ClusterConfig {

    repeated Folder folders = 1;
}
message Folder {

    string id                    = 1;

    string label                 = 2;

    FolderType type              = 3;

    FolderStopReason stop_reason = 7;

    reserved 4 to 6;

    repeated Device devices = 16;
}
message Device {

    bytes           id                         = 1;

    string          name                       = 2;

    repeated string addresses                  = 3;

    Compression     compression                = 4;

    string          cert_name                  = 5;

    int64           max_sequence               = 6;

    bool            introducer                 = 7;

    uint64          index_id                   = 8;

    bool            skip_introduction_removals = 9;

    bytes           encryption_password_token  = 10;
}
enum Compression {

    METADATA = 0;

    NEVER    = 1;

    ALWAYS   = 2;
}
enum FolderType {

    FOLDER_TYPE_SEND_RECEIVE      = 0;

    FOLDER_TYPE_SEND_ONLY         = 1;

    FOLDER_TYPE_RECEIVE_ONLY      = 2;

    FOLDER_TYPE_RECEIVE_ENCRYPTED = 3;
}
enum FolderStopReason {

    FOLDER_STOP_REASON_RUNNING = 0;

    FOLDER_STOP_REASON_PAUSED  = 1;
}
```

### Fields (Cluster Config Message)
The folders field contains the list of folders that will be synchronized over the current connection.

### Fields (Folder Message)
The id field contains the folder ID, which is the unique identifier of the folder.

The label field contains the folder label, the human readable name of the folder.

The folder_type field contains the type of the folder as defined by the FolderType enumeration.

The stop_reason field is set for folders that are currently stopped for any reason. The zero means that the folder is not stopped; further reasons are defined by the FolderStopReason enumeration.

The devices field is a list of devices participating in sharing this folder.

### Fields (Device Message)
The device id field is a 32 byte number that uniquely identifies the device. For instance, the reference implementation uses the SHA-256 of the device X.509 certificate.

The name field is a human readable name assigned to the described device by the sending device. It MAY be empty and it need not be unique.

The list of addresses is that used by the sending device to connect to the described device.

The compression field indicates the compression mode in use for this device and folder. The following values are valid:

0

Compress metadata. This enables compression of metadata messages such as Index.

1

Compression disabled. No compression is used on any message.

2

Compress always. Metadata messages as well as Response messages are compressed.

The cert_name field indicates the expected certificate name for this device. It is commonly blank, indicating to use the implementation default.

The max_sequence field contains the highest sequence number of the files in the index. See Delta Index Exchange for the usage of this field.

The introducer field is set for devices that are trusted as cluster introducers.

The index_id field contains the unique identifier for the current set of index data. See Delta Index Exchange for the usage of this field.

The skip_introduction_removals field signifies if the remote device has opted to ignore introduction removals for the given device. This setting is copied across as we are being introduced to a new device.

The encryption_password_token field contains a token derived from the password, that is used to encrypt data sent to this device. If the device is the same as the device sending the message, it signifies that the device itself has encrypted data that was encrypted with the given token. It is empty or missing if there is no encryption. See Untrusted Device Encryption for details on the encryption scheme.

### Index and Index Update
The Index and Index Update messages define the contents of the senders folder. An Index message represents the full contents of the folder and thus supersedes any previous index. An Index Update amends an existing index with new information, not affecting any entries not included in the message. An Index Update MAY NOT be sent unless preceded by an Index, unless a non-zero Max Sequence has been announced for the given folder by the peer device.

The Index and Index Update messages are currently identical in format, although this is not guaranteed to be the case in the future.

### Protocol Buffer Schema

```
message Index {

    string            folder = 1;

    repeated FileInfo files  = 2;
}
message IndexUpdate {

    string            folder = 1;

    repeated FileInfo files  = 2;
}
message FileInfo {

    string       name           = 1;

    FileInfoType type           = 2;

    int64        size           = 3;

    uint32       permissions    = 4;

    int64        modified_s     = 5;

    int32        modified_ns    = 11;

    uint64       modified_by    = 12;

    bool         deleted        = 6;

    bool         invalid        = 7;

    bool         no_permissions = 8;

    Vector       version        = 9;

    int64        sequence       = 10;

    int32        block_size     = 13;

    repeated BlockInfo Blocks         = 16;

    string             symlink_target = 17;
}
enum FileInfoType {

    FILE              = 0;

    DIRECTORY         = 1;

    SYMLINK_FILE      = 2 [deprecated = true];

    SYMLINK_DIRECTORY = 3 [deprecated = true];

    SYMLINK           = 4;
}
message BlockInfo {

    int64 offset = 1;

    int32 size   = 2;

    bytes hash   = 3;

    reserved 4;
}
message Vector {

    repeated Counter counters = 1;
}
message Counter {

    uint64 id    = 1;

    uint64 value = 2;
}
```

### Fields (Index Message)
The folder field identifies the folder that the index message pertains to.

The files field is a list of files making up the index information.

### Fields (FileInfo Message)
The name is the file name path relative to the folder root. Like all strings in BEP, the Name is always in UTF-8 NFC regardless of operating system or file system specific conventions. The name field uses the slash character (“/”) as path separator, regardless of the implementation’s operating system conventions. The combination of folder and name uniquely identifies each file in a cluster.

The type field contains the type of the described item. The type is one of file (0), directory (1), or symlink (4).

The size field contains the size of the file, in bytes. For directories and symlinks the size is zero.

The permissions field holds the common Unix permission bits. An implementation MAY ignore or interpret these as is suitable on the host operating system.

The modified_s time is expressed as the number of seconds since the Unix Epoch (1970-01-01 00:00:00 UTC). The modified_ns field holds the nanosecond part of the modification time.

The modified_by field holds the short id of the client that last made any modification to the file whether add, change or delete. This will be overwritten every time a change is made to the file by the last client to do so and so does not hold history.

The deleted field is set when the file has been deleted. The block list SHALL be of length zero and the modification time indicates the time of deletion or, if the time of deletion is not reliably determinable, the last known modification time.

The invalid field is set when the file is invalid and unavailable for synchronization. A peer MAY set this bit to indicate that it can temporarily not serve data for the file.

The no_permissions field is set when there is no permission information for the file. This is the case when it originates on a file system which does not support permissions. Changes to only permission bits SHOULD be disregarded on files with this bit set. The permissions bits MUST be set to the octal value 0666.

The version field is a version vector describing the updates performed to a file by all members in the cluster. Each counter in the version vector is an ID-Value tuple. The ID is the first 64 bits of the device ID. The Value is a simple incrementing counter, starting at zero. The combination of Folder, Name and Version uniquely identifies the contents of a file at a given point in time.

The sequence field is the value of a device local monotonic clock at the time of last local database update to a file. The clock ticks on every local database update, thus forming a sequence number over database updates.

The block_size field is the size, in bytes, of each individual block in the block list (except, possibly, the last block). If this field is missing or zero, the block size is assumed to be 128 KiB (131072 bytes). Valid values of this field are the powers of two from 128 KiB through 16 MiB. See also Selection of Block Size.

The blocks list contains the size and hash for each block in the file. Each block represents a block_size-sized slice of the file, except for the last block which may represent a smaller amount of data. The block list is empty for directories and symlinks.

The symlink_target field contains the symlink target, for entries of symlink type. It is empty for all other entry types.

### Request
The Request message expresses the desire to receive a data block corresponding to a part of a certain file in the peer’s folder.

### Protocol Buffer Schema

```
message Request {

    int32  id             = 1;

    string folder         = 2;

    string name           = 3;

    int64  offset         = 4;

    int32  size           = 5;

    bytes  hash           = 6;

    bool   from_temporary = 7;

    int32 block_no        = 9;

    reserved 8;
}
```

### Fields
The id is the request identifier. It will be matched in the corresponding Response message. Each outstanding request must have a unique ID.

The folder and name fields are as documented for the Index message. The offset and size fields specify the region of the file to be transferred. This SHOULD equate to exactly one block as seen in an Index message.

The hash field MAY be set to the expected hash value of the block. If set, the other device SHOULD ensure that the transmitted block matches the requested hash. The other device MAY reuse a block from a different file and offset having the same size and hash, if one exists.

The from_temporary field is set to indicate that the read should be performed from the temporary file (converting name to it’s temporary form) and falling back to the non temporary file if any error occurs. Knowledge of contents of temporary files comes from DownloadProgress messages.

### Response
The Response message is sent in response to a Request message.

### Protocol Buffer Schema

```
message Response {

    int32     id   = 1;

    bytes     data = 2;

    ErrorCode code = 3;
}
enum ErrorCode {

    NO_ERROR     = 0;

    GENERIC      = 1;

    NO_SUCH_FILE = 2;

    INVALID_FILE = 3;
}
```

### Fields
The id field is the request identifier. It must match the ID of the Request that is being responded to.

The data field contains either the requested data block or is empty if the requested block is not available.

The code field contains an error code describing the reason a Request could not be fulfilled, in the case where zero length data was returned. The following values are defined:

0

No Error (data should be present)

1

Generic Error

2

No Such File (the requested file does not exist, or the offset is outside the acceptable range for the file)

3

Invalid (file exists but has invalid bit set or is otherwise unavailable)

### DownloadProgress
The DownloadProgress message is used to notify remote devices about partial availability of files. By default, these messages are sent every 5 seconds, and only in the cases where progress or state changes have been detected. Each DownloadProgress message is addressed to a specific folder and MUST contain zero or more FileDownloadProgressUpdate messages.

### Protocol Buffer Schema

```
message DownloadProgress {

    string                              folder  = 1;

    repeated FileDownloadProgressUpdate updates = 2;
}
message FileDownloadProgressUpdate {

    FileDownloadProgressUpdateType update_type   = 1;

    string                         name          = 2;

    Vector                         version       = 3;

    repeated int32                 block_indexes = 4;
}
enum FileDownloadProgressUpdateType {

    APPEND = 0;

    FORGET = 1;
}
```

### Fields (DownloadProgress Message)
The folder field represents the ID of the folder for which the update is being provided.

The updates field is a list of progress update messages.

### Fields (FileDownloadProgressUpdate Message)
The update_type indicates whether the update is of type append (0) (new blocks are available) or forget (1) (the file transfer has completed or failed).

The name field defines the file name from the global index for which this update is being sent.

The version message defines the version of the file for which this update is being sent.

The block_indexes field is a list of positive integers, where each integer represents the index of the block in the FileInfo message Blocks array that has become available for download.

For example an integer with value 3 represents that the data defined in the fourth BlockInfo message of the FileInfo message of that file is now available. Please note that matching should be done on name AND version. Furthermore, each update received is incremental, for example the initial update message might contain indexes 0, 1, 2, an update 5 seconds later might contain indexes 3, 4, 5 which should be appended to the original list, which implies that blocks 0-5 are currently available.

Block indexes MAY be added in any order. An implementation MUST NOT assume that block indexes are added in any specific order.

The forget field being set implies that previously advertised file is no longer available, therefore the list of block indexes should be truncated.

Messages with the forget field set MUST NOT have any block indexes.

Any update message which is being sent for a different version of the same file name must be preceded with an update message for the old version of that file with the forget field set.

As a safeguard on the receiving side, the value of version changing between update messages implies that the file has changed and that any indexes previously advertised are no longer available. The list of available block indexes MUST be replaced (rather than appended) with the indexes specified in this message.

### Ping
The Ping message is used to determine that a connection is alive, and to keep connections alive through state tracking network elements such as firewalls and NAT gateways. A Ping message is sent every 90 seconds, if no other message has been sent in the preceding 90 seconds.

### Protocol Buffer Schema

```
message Ping {
}
```

### Close
The Close message MAY be sent to indicate that the connection will be torn down due to an error condition. A Close message MUST NOT be followed by further messages.

### Protocol Buffer Schema

```
message Close {

    string reason = 1;
}
```

### Fields
The reason field contains a human readable description of the error condition.

## SHARING MODES

### Trusted
Trusted mode is the default sharing mode. Updates are exchanged in both directions.

```
+------------+     Updates      /---------\
|            |  ----------->   /           \
|   Device   |                 |  Cluster  |
|            |  <-----------   \           /
+------------+     Updates      \---------/
```

### Send Only
In send only mode, a device does not apply any updates from the cluster, but publishes changes of its local folder to the cluster as usual.

```
+------------+     Updates      /---------\
|            |  ----------->   /           \
|   Device   |                 |  Cluster  |
|            |                 \           /
+------------+                  \---------/
```

### Receive Only
In receive only mode, a device does not send any updates to the cluster, but accepts changes to its local folder from the cluster as usual.

```
+------------+     Updates      /---------\
|            |  <-----------   /           \
|   Device   |                 |  Cluster  |
|            |                 \           /
+------------+                  \---------/
```

## DELTA INDEX EXCHANGE
Index data must be exchanged whenever two devices connect so that one knows the files available on the other. In the most basic case this happens by way of sending an Index message followed by one or more Index Update messages. Any previous index data known for a remote device is removed and replaced with the new index data received in an Index message, while the contents of an Index Update message is simply added to the existing index data.

For situations with large indexes or frequent reconnects this can be quite inefficient. A mechanism can then be used to retain index data between connections and only transmit any changes since that data on connection start. This is called “delta indexes”. To enable this mechanism the sequence and index ID fields are used.

Sequence:

Each index item (i.e., file, directory or symlink) has a sequence number field. It contains the value of a counter at the time the index item was updated. The counter increments by one for each change. That is, as files are scanned and added to the index they get assigned sequence numbers 1, 2, 3 and so on. The next file to be changed or detected gets sequence number 4, and future updates continue in the same fashion.

Index ID:

Each folder has an Index ID. This is a 64 bit random identifier set at index creation time.

Given the above, we know that the tuple {index ID, maximum sequence number} uniquely identifies a point in time of a given index. Any further changes will increase the sequence number of some item, and thus the maximum sequence number for the index itself. Should the index be reset or removed (i.e., the sequence number reset to zero), a new index ID must be generated.

By letting a device know the {index ID, maximum sequence number} we have for their index data, that device can arrange to only transmit Index Update messages for items with a higher sequence number. This is the delta index mechanism.

The index ID and maximum sequence number known for each device is transmitted in the Cluster Config message at connection start.

For this mechanism to be reliable it is essential that outgoing index information is ordered by increasing sequence number. Devices announcing a non-zero index ID in the Cluster Config message MUST send all index data ordered by increasing sequence number. Devices not intending to participate in delta index exchange MUST send a zero index ID or, equivalently, not send the index_id attribute at all.

## MESSAGE LIMITS
An implementation MAY impose reasonable limits on the length of messages and message fields to aid robustness in the face of corruption or broken implementations. An implementation should strive to keep messages short and to the point, favouring more and smaller messages over fewer and larger. For example, favour a smaller Index message followed by one or more Index Update messages rather than sending a very large Index message.

The Syncthing implementation imposes a hard limit of 500,000,000 bytes on all messages. Attempting to send or receive a larger message will result in a connection close. This size was chosen to accommodate Index messages containing a large block list. It’s intended that the limit may be further reduced in a future protocol update supporting variable block sizes (and thus shorter block lists for large files).

## SELECTION OF BLOCK SIZE
The desired block size for any given file is the smallest block size that results in fewer than 2000 blocks, or the maximum block size for larger files. This rule results in the following table of block sizes per file size:

File Size

Block Size

0 - 250 MiB

128 KiB

250 MiB - 500 MiB

256 KiB

500 MiB - 1 GiB

512 KiB

1 GiB - 2 GiB

1 MiB

2 GiB - 4 GiB

2 MiB

4 GiB - 8 GiB

4 MiB

8 GiB - 16 GiB

8 MiB

16 GiB - up

16 MiB

An implementation MAY deviate from the block size rule when there is good reason to do so. For example, if a file has been indexed at a certain block size and grows beyond 2000 blocks it may be retained at the current block size for practical reasons. When there is no overriding reason to the contrary, such as when indexing a new file for the first time, the block size rule above SHOULD be followed.

An implementation MUST therefore accept files with a block size differing from the above rule. This does not mean that arbitrary block sizes are allowed. The block size used MUST be exactly one of the power-of-two block sizes listed in the table above.

## EXAMPLE EXCHANGE
\#

A

B

1

ClusterConfiguration->

<-ClusterConfiguration

2

Index->

<-Index

3

IndexUpdate->

<-IndexUpdate

4

IndexUpdate->

5

Request->

6

Request->

7

Request->

8

Request->

9

<-Response

10

<-Response

11

<-Response

12

<-Response

13

Index Update->

…

14

<-Ping

15

Ping->

The connection is established and at 1. both peers send ClusterConfiguration messages and then Index records. The Index records are received and both peers recompute their knowledge of the data in the cluster. In this example, peer A has four missing or outdated blocks. At 5 through 8 peer A sends requests for these blocks. The requests are received by peer B, who retrieves the data from the folder and transmits Response records (9 through 12). Device A updates their folder contents and transmits an Index Update message (13). Both peers enter idle state after 13. At some later time 14, the ping timer on device B expires and a Ping message is sent. The same process occurs for device A at 15.

## AUTHOR
The Syncthing Authors

## COPYRIGHT
2014-2026, The Syncthing Authors


syncthing-device-ids

title: syncthing-device-ids(7)

summary: Understanding Device IDs

text:
# syncthing-device-ids(7)

## NAME
syncthing-device-ids - Understanding Device IDs

Every device is identified by a device ID. The device ID is used for address resolution, authentication and authorization. The term “device ID” could interchangeably have been “key ID” since the device ID is a direct property of the public key in use.

## KEYS
To understand device IDs we need to look at the underlying mechanisms. At first startup, Syncthing will create a public/private keypair.

Currently this is a 384 bit ECDSA key (3072 bit RSA prior to v0.12.5, which is what is used as an example in this article). The keys are saved in the form of the private key (key.pem) and a self signed certificate (cert.pem). The self signing part doesn’t actually add any security or functionality as far as Syncthing is concerned but it enables the use of the keys in a standard TLS exchange.

The typical certificate will look something like this, inspected with openssl x509:

```
Certificate:

    Data:

        Version: 3 (0x2)

        Serial Number: 0 (0x0)

        Signature Algorithm: sha1WithRSAEncryption

        Issuer: CN=syncthing

        Validity

            Not Before: Mar 30 21:10:52 2014 GMT

            Not After : Dec 31 23:59:59 2049 GMT

        Subject: CN=syncthing

        Subject Public Key Info:

            Public Key Algorithm: rsaEncryption

            RSA Public Key: (3072 bit)

                Modulus (3072 bit):

                    00:da:83:8a:c0:95:af:0a:42:af:43:74:65:29:f2:

                    30:e3:b9:12:d2:6b:70:93:da:0b:7b:8a:1e:e5:79:

                    ...

                    99:09:4c:a9:7b:ba:4a:6a:8b:3b:e6:e7:c7:2c:00:

                    90:aa:bc:ad:94:e7:80:95:d2:1b

                Exponent: 65537 (0x10001)

        X509v3 extensions:

            X509v3 Key Usage: critical

                Digital Signature, Key Encipherment

            X509v3 Extended Key Usage:

                TLS Web Server Authentication, TLS Web Client Authentication

            X509v3 Basic Constraints: critical

                CA:FALSE

    Signature Algorithm: sha1WithRSAEncryption

        68:72:43:8b:83:61:09:68:f0:ef:f0:43:b7:30:a6:73:1e:a8:

        d9:24:6c:2d:b4:bc:c9:e8:3e:0b:1e:3c:cc:7a:b2:c8:f1:1d:

        ...

        88:7e:e2:61:aa:4c:02:e3:64:b0:da:70:3a:cd:1c:3d:86:db:

        df:54:b9:4e:be:1b
```

We can see here that the certificate is little more than a container for the public key; the serial number is zero and the Issuer and Subject are both “syncthing” where a qualified name might otherwise be expected.

An advanced user could replace the key.pem and cert.pem files with a keypair generated directly by the openssl utility or other mechanism.

## DEVICE IDS
To form a device ID the SHA-256 hash of the certificate data in DER form is calculated. This means the hash covers all information under the Certificate: section above.

The hashing results in a 256 bit hash which we encode using base32. Base32 encodes five bits per character so we need 256 / 5 = 51.2 characters to encode the device ID. This becomes 52 characters in practice, but 52 characters of base32 would decode to 260 bits which is not a whole number of bytes. The base32 encoding adds padding to 280 bits (the next multiple of both 5 and 8 bits) so the resulting ID looks something like:

```
MFZWI3DBONSGYYLTMRWGC43ENRQXGZDMMFZWI3DBONSGYYLTMRWA====
```

The padding (====) is stripped away, the device ID split into four groups, and check digits <https://forum.syncthing.net/t/v0-9-0-new-node-id-format/478> are added for each group. For presentation purposes the device ID is grouped with dashes, resulting in the final value:

```
MFZWI3D-BONSGYC-YLTMRWG-C43ENR5-QXGZDMM-FZWI3DP-BONSGYY-LTMRWAD
```

### Connection Establishment
Now we know what device IDs are, here’s how they are used in Syncthing. When you add a device ID to the configuration, Syncthing will attempt to connect to that device. The first thing we need to do is figure out the IP and port to connect to. There are three possibilities here:

- The IP and port can be set statically in the configuration. The IP can equally well be a host name, so if you have a static IP or a dynamic DNS setup this might be a good option.

- Using local discovery, if enabled. Every Syncthing instance on a LAN periodically broadcasts information about itself (device ID, address, port number). If we’ve seen one of these broadcasts for a given device ID that’s where we try to connect.

- Using global discovery, if enabled. Every Syncthing instance announces itself to the global discovery service (device ID and external port number - the internal address is not announced to the global server). If we don’t have a static address and haven’t seen any local announcements the global discovery server will be queried for an address.

Once we have an address and port a TCP connection is established and a TLS handshake performed. As part of the handshake both devices present their certificates. Once the handshake has completed and the peer certificate is known, the following steps are performed:

1.

Calculate the remote device ID by processing the received certificate as above.

2.

Weed out a few possible misconfigurations - i.e. if the device ID is that of the local device or of a device we already have an active connection to. Drop the connection in these cases.

3.

Verify the remote device ID against the configuration. If it is not a device ID we are expecting to talk to, drop the connection.

4.

Verify the certificate CommonName against the configuration. By default, we expect it to be syncthing, but when using custom certificates this can be changed.

5.

If everything checks out so far, accept the connection.

## AN ASIDE ABOUT COLLISIONS
The SHA-256 hash is cryptographically collision resistant. This means that there is no way that we know of to create two different messages with the same hash.

You can argue that of course there are collisions - there’s an infinite amount of inputs and a finite amount of outputs - so by definition there are infinitely many messages that result in the same hash.

I’m going to quote stack overflow <https://stackoverflow.com/questions/4014090/is-it-safe-to-ignore-the-possibility-of-sha-collisions-in-practice> here:

The usual answer goes thus: what is the probability that a rogue asteroid crashes on Earth within the next second, obliterating civilization-as-we- know-it, and killing off a few billion people ? It can be argued that any unlucky event with a probability lower than that is not actually very important. If we have a “perfect” hash function with output size n, and we have p messages to hash (individual message length is not important), then probability of collision is about p2/2n+1 (this is an approximation which is valid for “small” p, i.e. substantially smaller than 2n/2). For instance, with SHA-256 (n=256) and one billion messages (p=10^9) then the probability is about 4.3*10^-60.

A mass-murderer space rock happens about once every 30 million years on average. This leads to a probability of such an event occurring in the next second to about 10^-15. That’s 45 orders of magnitude more probable than the SHA-256 collision. Briefly stated, if you find SHA-256 collisions scary then your priorities are wrong.

It’s also worth noting that the property of SHA-256 that we are using is not simply collision resistance but resistance to a preimage attack, i.e. even if you can find two messages that result in a hash collision that doesn’t help you attack Syncthing (or TLS in general). You need to create a message that hashes to exactly the hash that my certificate already has or you won’t get in.

Note also that it’s not good enough to find a random blob of bits that happen to have the same hash as my certificate. You need to create a valid DER-encoded, signed certificate that has the same hash as mine. The difficulty of this is staggeringly far beyond the already staggering difficulty of finding a SHA-256 collision.

## PROBLEMS AND VULNERABILITIES
As far as I know, these are the issues or potential issues with the above mechanism.

### Discovery Spoofing
Currently, the local discovery mechanism isn’t protected by crypto. This means that any device can in theory announce itself for any device ID and potentially receive connections for that device from the local network.

### Long Device IDs are Painful
It’s a mouthful to read over the phone, annoying to type into an SMS or even into a computer. And it needs to be done twice, once for each side.

This isn’t a vulnerability as such, but a user experience problem. There are various possible solutions:

- Use shorter device IDs with verification based on the full ID (“You entered MFZWI3; I found and connected to a device with the ID MFZWI3-DBONSG-YYLTMR-WGC43E-NRQXGZ-DMMFZW-I3DBON-SGYYLT-MRWA, please confirm that this is correct”).

- Use shorter device IDs with an out of band authentication, a la Bluetooth pairing. You enter a one time PIN into Syncthing and give that PIN plus a short device ID to another user. On initial connect, both sides verify that the other knows the correct PIN before accepting the connection.

## AUTHOR
The Syncthing Authors

## COPYRIGHT
2014-2026, The Syncthing Authors


syncthing-event-api

title: syncthing-event-api(7)

summary: Event API

text:
# syncthing-event-api(7)

## NAME
syncthing-event-api - Event API

## DESCRIPTION
Syncthing provides a simple long polling interface for exposing events from the core utility towards a GUI. To receive events, see GET /rest/events.

## EVENT STRUCTURE
Each event is represented by an object similar to the following:

```
{

    "id": 2,

    "globalID": 3,

    "type": "DeviceConnected",

    "time": "2014-07-13T21:04:33.687836696+02:00",

    "data": {

        "addr": "172.16.32.25:22000",

        "id": "NFGKEKE-7Z6RTH7-I3PRZXS-DEJF3UJ-FRWJBFO-VBBTDND-4SGNGVZ-QUQHJAG"

    }
}
```

The top level keys id, globalID, time, type and data are always present, though data may be null.

id

A unique ID for this event on the events API. It always increases by 1: the first event generated has id 1, the next has id 2 etc. If this increases by more than 1, then one or more events have been skipped by the events API.

globalID

A global ID for this event, across the events API, the audit log, and any other sources. It may increase by more than 1, but it will always be greater than or equal to the id.

time

The time the event was generated.

type

Indicates the type of (i.e. reason for) the event and is one of the event types below.

data

An object containing optional extra information; the exact structure is determined by the event type.

## EVENT TYPES

### ClusterConfigReceived
Added in version 1.20.0.

The ClusterConfigReceived event is emitted after processing such a protocol message received from a remote device. It is mainly used for internal purposes.

```
{

    "id": 84,

    "globalID": 84,

    "type": "ClusterConfigReceived",

    "time": "2022-04-27T14:14:27.043576583+09:00",

    "data": {

        "device": "I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU"

    }
}
```

### ConfigSaved
Emitted after the config has been saved by the user or by Syncthing itself.

```
{

    "id": 50,

    "globalID": 50,

    "type": "ConfigSaved",

    "time": "2014-12-13T00:09:13.5166486Z",

    "data": {

        "version": 7,

        "folders": [{"..."}],

        "devices": [{"..."}],

        "gui": {"..."},

        "ldap": {"..."},

        "options": {"..."},

        "remoteIgnoredDevices": [{"..."}],

        "defaults": {"..."}

    }
}
```

### DeviceConnected
Generated each time a connection to a device has been established.

```
{

    "id": 2,

    "globalID": 2,

    "type": "DeviceConnected",

    "time": "2014-07-13T21:04:33.687836696+02:00",

    "data": {

        "addr": "172.16.32.25:22000",

        "id": "NFGKEKE-7Z6RTH7-I3PRZXS-DEJF3UJ-FRWJBFO-VBBTDND-4SGNGVZ-QUQHJAG",

        "deviceName": "Laptop",

        "clientName": "syncthing",

        "clientVersion": "v0.13.4",

        "type": "TCP (Client)"

    }
}
```

### DeviceDisconnected
Generated each time a connection to a device has been terminated.

```
{

    "id": 48,

    "globalID": 48,

    "type": "DeviceDisconnected",

    "time": "2014-07-13T21:18:52.859929215+02:00",

    "data": {

        "error": "unexpected EOF",

        "id": "NFGKEKE-7Z6RTH7-I3PRZXS-DEJF3UJ-FRWJBFO-VBBTDND-4SGNGVZ-QUQHJAG"

    }
}
```

NOTE:

The error key contains the cause for disconnection, which might not necessarily be an error as such. Specifically, “EOF” and “unexpected EOF” both signify TCP connection termination, either due to the other device restarting or going offline or due to a network change.

### DeviceDiscovered
Emitted when a new device is discovered using local discovery.

```
{

    "id": 13,

    "globalID": 13,

    "type": "DeviceDiscovered",

    "time": "2014-07-17T13:28:05.043465207+02:00",

    "data": {

        "addrs": [

            "172.16.32.25:22000"

        ],

        "device": "NFGKEKE-7Z6RTH7-I3PRZXS-DEJF3UJ-FRWJBFO-VBBTDND-4SGNGVZ-QUQHJAG"

    }
}
```

### DevicePaused
Emitted when a device was paused.

```
{

    "id": 13,

    "globalID": 13,

    "type": "DevicePaused",

    "time": "2014-07-17T13:28:05.043465207+02:00",

    "data": {

        "device": "NFGKEKE-7Z6RTH7-I3PRZXS-DEJF3UJ-FRWJBFO-VBBTDND-4SGNGVZ-QUQHJAG"

    }
}
```

### DeviceRejected (DEPRECATED)
Deprecated since version v1.13.0: This event is still emitted for compatibility, but deprecated. Use the replacement PendingDevicesChanged event instead.

Emitted when there is a connection from a device we are not configured to talk to.

```
{

    "id": 24,

    "globalID": 24,

    "type": "DeviceRejected",

    "time": "2014-08-19T10:43:00.562821045+02:00",

    "data": {

        "address": "127.0.0.1:51807",

        "name": "My dusty computer",

        "device": "EJHMPAQ-OGCVORE-ISB4IS3-SYYVJXF-TKJGLTU-66DIQPF-GJ5D2GX-GQ3OWQK"

    }
}
```

### DeviceResumed
Generated each time a device was resumed.

```
{

    "id": 2,

    "globalID": 2,

    "type": "DeviceResumed",

    "time": "2014-07-13T21:04:33.687836696+02:00",

    "data": {

        "device": "NFGKEKE-7Z6RTH7-I3PRZXS-DEJF3UJ-FRWJBFO-VBBTDND-4SGNGVZ-QUQHJAG"

    }
}
```

### DownloadProgress
Emitted during file downloads for each folder for each file. By default only a single file in a folder is handled at the same time, but custom configuration can cause multiple files to be shown.

```
{

    "id": 221,

    "globalID": 221,

    "type": "DownloadProgress",

    "time": "2014-12-13T00:26:12.9876937Z",

    "data": {

        "folder1": {

            "file1": {

                "total": 800,

                "pulling": 2,

                "copiedFromOrigin": 0,

                "reused": 633,

                "copiedFromElsewhere": 0,

                "pulled": 38,

                "bytesTotal": 104792064,

                "bytesDone": 87883776

            },

            "dir\\file2": {

                "total": 80,

                "pulling": 2,

                "copiedFromOrigin": 0,

                "reused": 0,

                "copiedFromElsewhere": 0,

                "pulled": 32,

                "bytesTotal": 10420224,

                "bytesDone": 4128768

            }

        },

        "folder2": {

            "file3": {

                "total": 800,

                "pulling": 2,

                "copiedFromOrigin": 0,

                "reused": 633,

                "copiedFromElsewhere": 0,

                "pulled": 38,

                "bytesTotal": 104792064,

                "bytesDone": 87883776

            },

            "dir\\file4": {

                "total": 80,

                "pulling": 2,

                "copiedFromOrigin": 0,

                "reused": 0,

                "copiedFromElsewhere": 0,

                "pulled": 32,

                "bytesTotal": 10420224,

                "bytesDone": 4128768

            }

        }

    }
}
```

- total - total number of blocks in the file

- pulling - number of blocks currently being downloaded

- copiedFromOrigin - number of blocks copied from the file we are about to replace

- reused - number of blocks reused from a previous temporary file

- copiedFromElsewhere - number of blocks copied from other files or potentially other folders

- pulled - number of blocks actually downloaded so far

- bytesTotal - approximate total file size

- bytesDone - approximate number of bytes already handled (already reused, copied or pulled)

Where block size is 128KB.

Files/folders appearing in the event data imply that the download has been started for that file/folder, where disappearing implies that the downloads have been finished or failed for that file/folder. There is always a last event emitted with no data, which implies all downloads have finished/failed.

### Failure
Generated for specific errors that will also be sent to the usage reporting server, if enabled in the configuration. These are usually of special interest to the developers to troubleshoot complex errors. The data field contains a textual error message.

```
{

  "id": 93,

  "globalID": 93,

  "type": "Failure",

  "time": "2021-06-07T21:22:03.414609034+02:00",

  "data": "index handler got paused while already paused"
}
```

### FolderCompletion
The FolderCompletion event is emitted when the local or remote contents for a folder changes. It contains the completion percentage for a given remote device and is emitted once per currently connected remote device.

Added in version 1.20.0: Indication whether the remote device has accepted the folder (shares it with us) as well, and whether it is paused. The remoteState field is unknown when the remote device is not connected. Otherwise it can be either paused, notSharing, or valid if the remote is sharing back.

```
{

    "id": 84,

    "globalID": 84,

    "type": "FolderCompletion",

    "time": "2022-04-27T14:14:27.043576583+09:00",

    "data": {

        "completion": 100,

        "device": "I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU",

        "folder": "default",

        "globalBytes": 17,

        "globalItems": 4,

        "needBytes": 0,

        "needDeletes": 0,

        "needItems": 0,

        "remoteState": "valid",

        "sequence": 12

    }
}
```

### FolderErrors
The FolderErrors event is emitted when a folder cannot be successfully synchronized. The event contains the ID of the affected folder and a list of errors for files or directories therein. This list of errors is obsolete once the folder changes state to syncing - if errors remain after the next synchronization attempt, a new FolderErrors event is emitted.

```
{

    "id": 132,

    "type": "FolderErrors",

    "time": "2015-06-26T13:39:24.697401384+02:00",

    "data": {

        "errors": [

            {

                "error": "open /Users/jb/src/github.com/syncthing/syncthing/test/s2/h2j/.syncthing.aslkjd.tmp: permission denied",

                "path": "h2j/aslkjd"

            }

        ],

        "folder": "default"

    }
}
```

Added in version 0.11.12.

SEE ALSO:

The StateChanged event.

### FolderPaused
Generated when the configuration changes regarding the “paused” state of a folder. Sent repeatedly for each changed folder.

```
{

  "id": 93,

  "globalID": 93,

  "type": "FolderPaused",

  "time": "2021-06-07T23:45:03.414609034+02:00",

  "data": {

    "id": "abcde-fghij",

    "label": "My folder"

  }
}
```

### FolderRejected (DEPRECATED)
Deprecated since version v1.13.0: This event is still emitted for compatibility, but deprecated. Use the replacement PendingFoldersChanged event instead.

Emitted when a device sends index information for a folder we do not have, or have but do not share with the device in question.

```
{

    "id": 27,

    "globalID": 27,

    "type": "FolderRejected",

    "time": "2014-08-19T10:41:06.761751399+02:00",

    "data": {

        "device": "EJHMPAQ-OGCVORE-ISB4IS3-SYYVJXF-TKJGLTU-66DIQPF-GJ5D2GX-GQ3OWQK",

        "folder": "GXWxf-3zgnU",

        "folderLabel": "My Pictures"

    }
}
```

### FolderResumed
Generated when the configuration changes regarding the “paused” state of a folder. Sent repeatedly for each changed folder.

```
{

  "id": 93,

  "globalID": 93,

  "type": "FolderResumed",

  "time": "2021-06-07T23:45:03.414609034+02:00",

  "data": {

    "id": "abcde-fghij",

    "label": "My folder"

  }
}
```

### FolderScanProgress
Emitted in regular intervals (folder setting ProgressIntervalS, 2s by default) during scans giving the amount of bytes already scanned and to be scanned in total , as well as the current scanning rates in bytes per second.

```
{

   "data" : {

      "total" : 1,

      "rate" : 0,

      "current" : 0,

      "folder" : "bd7q3-zskm5"

   },

   "globalID" : 29,

   "type" : "FolderScanProgress",

   "time" : "2017-03-06T15:00:58.072004209+01:00",

   "id" : 29
}
```

### FolderSummary
The FolderSummary event is emitted when folder contents have changed locally. This can be used to calculate the current local completion state.

```
{

    "id": 16,

    "type": "FolderSummary",

    "time": "2024-01-31T08:27:30.777875+01:00",

    "data": {

        "folder": "default",

        "summary": {

            "error": "",

            "errors": 0,

            "globalBytes": 4,

            "globalDeleted": 18664,

            "globalDirectories": 0,

            "globalFiles": 1,

            "globalSymlinks": 0,

            "globalTotalItems": 18665,

            "ignorePatterns": false,

            "inSyncBytes": 4,

            "inSyncFiles": 1,

            "invalid": "",

            "localBytes": 4,

            "localDeleted": 18664,

            "localDirectories": 0,

            "localFiles": 1,

            "localSymlinks": 0,

            "localTotalItems": 18665,

            "needBytes": 0,

            "needDeletes": 0,

            "needDirectories": 0,

            "needFiles": 0,

            "needSymlinks": 0,

            "needTotalItems": 0,

            "pullErrors": 0,

            "receiveOnlyChangedBytes": 0,

            "receiveOnlyChangedDeletes": 0,

            "receiveOnlyChangedDirectories": 0,

            "receiveOnlyChangedFiles": 0,

            "receiveOnlyChangedSymlinks": 0,

            "receiveOnlyTotalItems": 0,

            "remoteSequence": {

                "MRIW7OK-NETT3M4-N6SBWME-N25O76W-YJKVXPH-FUMQJ3S-P57B74J-GBITBAC": 37329

            },

            "sequence": 37329,

            "state": "idle",

            "stateChanged": "2024-01-31T08:27:24+01:00",

            "version": 37329,

            "watchError": ""

        }

    }
}
```

### FolderWatchStateChanged
The FolderWatchStateChanged event is emitted when a folder’s watcher routine encounters a new error, or when a previous error disappeared after retrying. The event contains the ID of the affected folder and textual error messages describing the previous (from) and the updated (to) error conditions. If there was no error in either of these, the respective field is omitted.

```
{

  "id": 123,

  "type": "FolderWatchStateChanged",

  "time": "2022-03-14T12:34:56.890000000+01:00",

  "data": {

    "folder": "default",

    "from": "Something bad happened.",

    "to": "Something worse happened."

  }
}
```

### ItemFinished
Generated when Syncthing ends synchronizing a file to a newer version. A successful operation:

```
{

    "id": 93,

    "globalID": 93,

    "type": "ItemFinished",

    "time": "2014-07-13T21:22:03.414609034+02:00",

    "data": {

        "item": "test.txt",

        "folder": "default",

        "error": null,

        "type": "file",

        "action": "update"

    }
}
```

An unsuccessful operation:

```
{

    "id": 44,

    "globalID": 44,

    "type": "ItemFinished",

    "time": "2015-05-27T11:21:05.711133004+02:00",

    "data": {

        "action": "update",

        "error": "open /Users/jb/src/github.com/syncthing/syncthing/test/s2/foo/.syncthing.hej.tmp: permission denied",

        "folder": "default",

        "item": "foo/hej",

        "type": "file"

    }
}
```

The action field is either update (contents changed), metadata (file metadata changed but not contents), or delete.

Added in version 0.11.10: The metadata action.

### ItemStarted
Generated when Syncthing begins synchronizing a file to a newer version.

```
{

    "id": 93,

    "globalID": 93,

    "type": "ItemStarted",

    "time": "2014-07-13T21:22:03.414609034+02:00",

    "data": {

        "item": "test.txt",

        "folder": "default",

        "type": "file",

        "action": "update"

    }
}
```

The action field is either update (contents changed), metadata (file metadata changed but not contents), or delete.

Added in version 0.11.10: The metadata action.

### ListenAddressesChanged
This event is emitted when a listen address changes.

```
{

   "type" : "ListenAddressesChanged",

   "id" : 70,

   "time" : "2017-03-06T15:01:24.88340663+01:00",

   "globalID" : 70,

   "data" : {

      "address" : {

         "Fragment" : "",

         "RawQuery" : "",

         "Scheme" : "dynamic+https",

         "Path" : "/endpoint",

         "RawPath" : "",

         "User" : null,

         "ForceQuery" : false,

         "Host" : "relays.syncthing.net",

         "Opaque" : ""

      },

      "wan" : [

         {

            "ForceQuery" : false,

            "User" : null,

            "Host" : "31.15.66.212:443",

            "Opaque" : "",

            "Path" : "/",

            "RawPath" : "",

            "RawQuery" : "id=F4HSJVO-CP2C3IL-YLQYLSU-XTYODAG-PPU4LGV-PH3MU4N-G6K56DV-IPN47A&pingInterval=1m0s&networkTimeout=2m0s&sessionLimitBps=0&globalLimitBps=0&statusAddr=:22070&providedBy=",

            "Scheme" : "relay",

            "Fragment" : ""

         }

      ],

      "lan" : [

         {

            "RawQuery" : "id=F4HSJVO-CP2C3IL-YLQYLSU-XTYODAG-PPU4LGV-PH3MU4N-G6K56DV-IPN47A&pingInterval=1m0s&networkTimeout=2m0s&sessionLimitBps=0&globalLimitBps=0&statusAddr=:22070&providedBy=",

            "Scheme" : "relay",

            "Fragment" : "",

            "RawPath" : "",

            "Path" : "/",

            "Host" : "31.15.66.212:443",

            "Opaque" : "",

            "ForceQuery" : false,

            "User" : null

         }

      ]

   }
}
```

### LocalChangeDetected
Generated upon scan whenever the local disk has discovered an updated file from the previous scan. This does not include events that are discovered and copied from other devices (RemoteChangeDetected), only files that were changed on the local filesystem.

NOTE:

This event is not included in GET /rest/events endpoint without a mask specified, but needs to be selected explicitly.

```
{

  "id": 7,

  "globalID": 59,

  "time": "2016-09-26T22:07:10.7189141-04:00",

  "type": "LocalChangeDetected",

  "data": {

    "action": "deleted",

    "folder": "vitwy-zjxqt",

    "folderID": "vitwy-zjxqt",

    "label": "TestSync",

    "path": "test file.rtf",

    "type": "file"

  }
}
```

Deprecated since version v1.1.2: The folderID field is a legacy name kept only for compatibility. Use the folder field with identical content instead.

### LocalIndexUpdated
Generated when the local index information has changed, due to synchronizing one or more items from the cluster or discovering local changes during a scan.

```
{

    "id": 59,

    "globalID": 59,

    "type": "LocalIndexUpdated",

    "time": "2014-07-17T13:27:28.051369434+02:00",

    "data": {

        "folder": "default",

        "items": 1000,

        "filenames": [

            "foo",

            "bar",

            "baz"

        ],

        "sequence": 12345,

        "version": 12345

    }
}
```

Deprecated since version v1.10.0: The version field is a legacy name kept only for compatibility. Use the sequence field with identical content instead.

### LoginAttempt
When authentication is enabled for the GUI, this event is emitted on every login attempt. If either the username or password are incorrect, success is false and in any case the given username is returned.

```
{

   "id" : 187,

   "time" : "2017-03-07T00:19:24.420386143+01:00",

   "data" : {

      "remoteAddress" : "127.0.0.1",

      "username" : "somename",

      "success" : false

   },

   "type" : "LoginAttempt",

   "globalID" : 195
}
```

If the X-Forwared-For header is present and the connecting host is either on localhost or on the same LAN, it will be treated as a reverse proxy. In this case, the remoteAddress field is filled with the leftmost IP address from the header, and the additional proxy field retains the original IP of the connecting host.

```
{

   "id" : 187,

   "time" : "2017-03-07T00:19:24.420386143+01:00",

   "data" : {

      "proxy" : "127.0.0.1",

      "remoteAddress" : "192.168.178.10",

      "username" : "somename",

      "success" : false

   },

   "type" : "LoginAttempt",

   "globalID" : 195
}
```

### PendingDevicesChanged
Added in version 1.14.0.

Emitted when pending devices were added / updated (connection from unknown ID) or removed (device is ignored, dismissed or added).

```
{

  "id": 87,

  "type": "PendingDevicesChanged",

  "time": "2020-12-22T22:24:37.578586718+01:00",

  "data": {

    "added": [

      {

        "address": "127.0.0.1:51807",

        "deviceID": "EJHMPAQ-OGCVORE-ISB4IS3-SYYVJXF-TKJGLTU-66DIQPF-GJ5D2GX-GQ3OWQK",

        "name": "My dusty computer"

      }

    ],

    "removed": [

      {

        "deviceID": "P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"

      }

    ]

  }
}
```

### PendingFoldersChanged
Added in version 1.14.0.

Emitted when pending folders were added / updated (offered by some device, but not shared to them) or removed (folder ignored, dismissed or added or no longer offered from the remote device). A removed entry without a deviceID attribute means that the folder is no longer pending for any device.

```
{

  "id": 101,

  "type": "PendingFoldersChanged",

  "time": "2020-12-22T22:36:55.66744317+01:00",

  "data": {

    "added": [

      {

        "deviceID": "EJHMPAQ-OGCVORE-ISB4IS3-SYYVJXF-TKJGLTU-66DIQPF-GJ5D2GX-GQ3OWQK",

        "folderID": "GXWxf-3zgnU",

        "folderLabel": "My Pictures"

        "receiveEncrypted": "false"

        "remoteEncrypted": "false"

      }

    ],

    "removed": [

      {

        "deviceID": "P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2",

        "folderID": "neyfh-sa2nu"

      },

      {

        "folderID": "abcde-fghij"

      }

    ]

  }
}
```

### RemoteChangeDetected
Generated upon scan whenever a file is locally updated due to a remote change. Files that are updated locally produce a LocalChangeDetected event.

NOTE:

This event is not included in GET /rest/events endpoint without a mask specified, but needs to be selected explicitly.

```
{

   "time" : "2017-03-06T23:58:21.844739891+01:00",

   "globalID" : 123,

   "data" : {

      "type" : "file",

      "action" : "deleted",

      "folder": "Dokumente",

      "folderID" : "Dokumente",

      "path" : "testfile",

      "label" : "Dokumente",

      "modifiedBy" : "BPDFDTU"

   },

   "type" : "RemoteChangeDetected",

   "id" : 2
}
```

Deprecated since version v1.1.2: The folderID field is a legacy name kept only for compatibility. Use the folder field with identical content instead.

### RemoteDownloadProgress
This event is emitted when a DownloadProgress message is received. It returns a map data of filenames with a count of downloaded blocks. The files in questions are currently being downloaded on the remote device and belong to folder.

```
{

   "time" : "2017-03-07T00:11:37.65838955+01:00",

   "globalID" : 170,

   "data" : {

      "state" : {

         "tahr64-6.0.5.iso" : 1784

      },

      "device" : "F4HSJVO-CP2C3IL-YLQYLSU-XTYODAG-PPU4LGV-PH3MU4N-G6K56DV-IPN47A",

      "folder" : "Dokumente"

   },

   "type" : "RemoteDownloadProgress",

   "id" : 163
}
```

### RemoteIndexUpdated
Generated each time new index information is received from a device.

```
{

    "id": 44,

    "globalID": 44,

    "type": "RemoteIndexUpdated",

    "time": "2014-07-13T21:04:35.394184435+02:00",

    "data": {

        "device": "NFGKEKE-7Z6RTH7-I3PRZXS-DEJF3UJ-FRWJBFO-VBBTDND-4SGNGVZ-QUQHJAG",

        "folder": "lightroom",

        "items": 1000

    }
}
```

### Starting
Emitted exactly once, when Syncthing starts, before parsing configuration etc.

```
{

    "id": 1,

    "globalID": 1,

    "type": "Starting",

    "time": "2014-07-17T13:13:32.044470055+02:00",

    "data": {

        "home": "/home/jb/.config/syncthing"

    }
}
```

### StartupComplete
Emitted exactly once, when initialization is complete and Syncthing is ready to start exchanging data with other devices.

```
{

    "id": 1,

    "globalID": 1,

    "type": "StartupComplete",

    "time": "2014-07-13T21:03:18.383239179+02:00",

    "data": null
}
```

### StateChanged
Emitted when a folder changes state. Possible states are idle, scanning, syncing and error. The field duration is the number of seconds the folder spent in state from. In the example below, the folder default was in state scanning for 0.198 seconds and is now in state idle.

```
{

    "id": 8,

    "globalID": 8,

    "type": "StateChanged",

    "time": "2014-07-17T13:14:28.697493016+02:00",

    "data": {

        "folder": "default",

        "from": "scanning",

        "duration": 0.19782869900000002,

        "to": "idle"

    }
}
```

## AUTHOR
The Syncthing Authors

## COPYRIGHT
2014-2026, The Syncthing Authors


syncthing-faq

title: syncthing-faq(7)

summary: Frequently Asked Questions

text:
# syncthing-faq(7)

## NAME
syncthing-faq - Frequently Asked Questions

•

General

- What is Syncthing?

- Is it “syncthing”, “Syncthing” or “SyncThing”?

- What things are synced?

- Is synchronization fast?

- How does Syncthing differ from BitTorrent/Resilio Sync?

- Is there an iOS client?

- Should I keep my device IDs secret?

•

Troubleshooting

- Where are the Syncthing logs?

- Why is the sync so slow?

- Why does it use so much CPU?

- Why is the setup more complicated than BitTorrent/Resilio Sync?

- Why do I get “Host check error” in the GUI/API?

- My Syncthing database is corrupt

- Why do I see Syncthing twice in task manager?

- How can I view the history of changes?

- Does the audit log contain every change?

- Why does Syncthing connect to this unknown/suspicious address?

- I am seeing the error message “folder marker missing”. What do I do?

- Why do my Windows computers always connect through a relay?

•

Usage

- What if there is a conflict?

- How do I serve a folder from a read only filesystem?

- I really hate the .stfolder directory, can I remove it?

- Am I able to nest shared folders in Syncthing?

- How do I rename/move a synced folder?

- How do I configure multiple users on a single machine?

- Does Syncthing support syncing between folders on the same system?

- When I do have two distinct Syncthing-managed folders on two hosts, how does Syncthing handle moving files between them?

- Can I help initial sync by copying files manually?

- Is Syncthing my ideal backup application?

- How can I exclude files with brackets ([]) in the name?

- How do I access the web GUI from another computer?

- I don’t like the GUI or the theme. Can it be changed?

- How do I upgrade Syncthing?

- Where do I find the latest release?

- How do I run Syncthing as a daemon process on Linux?

- How do I increase the inotify limit to get my filesystem watcher to work?

- How do I reset the GUI password?

## GENERAL

### What is Syncthing?
Syncthing is an application that lets you synchronize your files across multiple devices. This means the creation, modification or deletion of files on one machine will automatically be replicated to your other devices. We believe your data is your data alone and you deserve to choose where it is stored. Therefore Syncthing does not upload your data to the cloud but exchanges your data across your machines as soon as they are online at the same time.

### Is it “syncthing”, “Syncthing” or “SyncThing”?
It’s Syncthing, although the command and source repository is spelled syncthing so it may be referred to in that way as well. It’s definitely not SyncThing, even though the abbreviation st is used in some circumstances and file names.

### What things are synced?
The following things are always synchronized:

- File contents

- File modification times

The following may be synchronized or not, depending:

- File permissions (when supported by file system; on Windows only the read only bit is synchronized)

- Symbolic links (synced, except on Windows, but never followed)

- File or directory owners and groups (when enabled)

- Extended attributes (when enabled)

- POSIX or NFS ACLs (as part of extended attributes)

NOTE:

Note that what can be synced often depends on the operating system, file system, and possibly other factors. For example, even though Syncthing may try to synchronise symbolic links on Android, this will not succeed, as the OS does not support them on the user storage.

The following are not synchronized;

- Directory modification times (not preserved)

- Hard links (followed, not preserved)

- Windows junctions (synced as ordinary directories; require enabling in the configuration on a per-folder basis)

- Resource forks (not preserved)

- Windows ACLs (not preserved)

- Devices, FIFOs, and other specials (ignored)

- Sparse file sparseness (will become sparse, when supported by the OS & filesystem)

- Syncthing internal files and folders (e.g. .stfolder, .stignore, .stversions, temporary files, etc.)

### Is synchronization fast?
Syncthing segments files into pieces, called blocks, to transfer data from one device to another. Therefore, multiple devices can share the synchronization load, in a similar way to the torrent protocol. The more devices you have online, the faster an additional device will receive the data because small blocks will be fetched from all devices in parallel.

Syncthing handles renaming files and updating their metadata in an efficient manner. This means that renaming a file will not cause a retransmission of that file. Additionally, appending data to existing files should be handled efficiently as well.

Temporary files are used to store partial data downloaded from other devices. They are automatically removed whenever a file transfer has been completed or after the configured amount of time which is set in the configuration file (24 hours by default).

### How does Syncthing differ from BitTorrent/Resilio Sync?
The two are different and not related. Syncthing and BitTorrent/Resilio Sync accomplish some of the same things, namely syncing files between two or more computers.

BitTorrent Sync, now called Resilio Sync, is a proprietary peer-to-peer file synchronization tool available for Windows, Mac, Linux, Android, iOS, Windows Phone, Amazon Kindle Fire and BSD. [1] Syncthing is an open source file synchronization tool.

Syncthing uses an open and documented protocol, and likewise the security mechanisms in use are well defined and visible in the source code. Resilio Sync uses an undocumented, closed protocol with unknown security properties.

[1]

https://en.wikipedia.org/wiki/Resilio_Sync

### Is there an iOS client?
There are no plans by the current Syncthing team to officially support iOS in the foreseeable future.

iOS has significant restrictions on background processing that make it very hard to run Syncthing reliably and integrate it into the system.

However, there is an open source app for iOS, incorporating Syncthing, that attempts to work within these limitations. It provides a native UI and features for selective synchronization as well as on-demand access to files. Most Syncthing features are available, but the native UI is simplified compared to the official client. [2]

There is also a commercial packaging of Syncthing. It provides access to all Syncthing functionalities through the original UI. [3]

[2]

https://github.com/pixelspark/sushitrain

[3]

https://www.mobiussync.com

### Should I keep my device IDs secret?
No. The IDs are not sensitive. Given a device ID it’s possible to find the IP address for that device, if global discovery is enabled on it. Knowing the device ID doesn’t help you actually establish a connection to that device or get a list of files, etc.

For a connection to be established, both devices need to know about the other’s device ID. It’s not possible (in practice) to forge a device ID. (To forge a device ID you need to create a TLS certificate with that specific SHA-256 hash. If you can do that, you can spoof any TLS certificate. The world is your oyster!)

SEE ALSO:

Understanding Device IDs

## TROUBLESHOOTING

### Where are the Syncthing logs?
Syncthing logs to stdout by default. On Windows Syncthing by default also creates syncthing.log in Syncthing’s home directory (run syncthing --paths to see where that is). The command line option --logfile can be used to specify a user-defined logfile. If you only have access to a running instance’s GUI, click the Help -> About menu item, then the Paths tab.

If you’re running a process manager like systemd, check there. If you’re using a GUI wrapper integration, it may keep the logs for you.

### Why is the sync so slow?
When troubleshooting a slow sync, there are a number of things to check.

First of all, verify that you are not connected via a relay. In the “Remote Devices” list on the right side of the GUI, double check that the Connection Type does not start with “Relay”.

Here is an example of a device connected via a relay: [image]

If you are connected via a relay, this is because a direct connection could not be established. Double check and follow the suggestions in Firewall Setup to enable direct connections.

Second, if one of the devices is a very low powered machine (a Raspberry Pi, or a phone, or a NAS, or similar) you are likely constrained by the CPU on that device. See the next question for reasons Syncthing likes a faster CPU.

Third, verify that the network connection is OK. Tools such as iperf or just an Internet speed test can be used to verify the performance here.

### Why does it use so much CPU?
1.

When new or changed files are detected, or Syncthing starts for the first time, your files are hashed using SHA-256.

2.

Data that is sent over the network is compressed (optionally) and encrypted (always). When receiving data it must be decrypted and then (if compressed) decompressed.

3.

There is a certain amount of housekeeping that must be done to track the current and available versions of each file in the index database.

4.

By default Syncthing uses periodic scanning every hour when watching for changes or every minute if that’s disabled to detect file changes. This means checking every file’s modification time and comparing it to the database. This can cause spikes of CPU usage for large folders.

Hashing, compression and encryption cost CPU time. Also, using the GUI causes a certain amount of extra CPU usage to calculate the summary data it presents. Note however that once things are in sync CPU usage should be negligible.

To minimize the impact of this, Syncthing attempts to lower the process priority when starting up.

To further limit the amount of CPU used when syncing and scanning, set the environment variable GOMAXPROCS to the maximum number of CPU cores Syncthing should use at any given moment. For example, GOMAXPROCS=2 on a machine with four cores will limit Syncthing to no more than half the system’s CPU power.

### Why is the setup more complicated than BitTorrent/Resilio Sync?
Security over convenience. In Syncthing you have to set up both sides to connect two devices. An attacker can’t do much with a stolen device ID, because you have to add the device on the other side too. You have better control where your files are transferred.

This is an area that we are working to improve in the long term.

### Why do I get “Host check error” in the GUI/API?
Since version 0.14.6 Syncthing does an extra security check when the GUI/API is bound to localhost - namely that the browser is talking to localhost. This protects against most forms of DNS rebinding attack <https://en.wikipedia.org/wiki/DNS_rebinding> against the GUI.

To pass this test, ensure that you are accessing the GUI using an URL that begins with http://localhost, http://127.0.0.1 or http://[::1]. HTTPS is fine too, of course.

If you are using a proxy in front of Syncthing you may need to disable this check, after ensuring that the proxy provides sufficient authentication to protect against unauthorized access. Either:

- Make sure the proxy sets a Host header containing localhost, or

- Set gui.insecureSkipHostcheck in the advanced settings, or

- Bind the GUI/API to a non-localhost listen port.

In all cases, username/password authentication and HTTPS should be used.

### My Syncthing database is corrupt
This is almost always a result of bad RAM, storage device or other hardware. When the index database is found to be corrupt Syncthing cannot operate and will note this in the logs and exit. To overcome this delete the database folder inside Syncthing’s data directory and re-start Syncthing. It will then need to perform a full re-hashing of all shared folders. You should check your system in case the underlying cause is indeed faulty hardware which may put the system at risk of further data loss.

### Why do I see Syncthing twice in task manager?
One process manages the other, to capture logs and manage restarts. This makes it easier to handle upgrades from within Syncthing itself, and also ensures that we get a nice log file to help us narrow down the cause for crashes and other bugs.

### How can I view the history of changes?
The web GUI contains a Recent Changes button under the device list which displays changes since the last (re)start of Syncthing. With the --audit option you can enable a persistent, detailed log of changes and most activities, which contains a JSON-formatted sequence of events in the ~/.local/state/syncthing/audit-_date_-_time_.log file.

### Does the audit log contain every change?
The audit log (and the Recent Changes window) sees the changes that your Syncthing sees. When Syncthing is continuously connected it usually sees every change happening immediately and thus knows which node initiated the change. When topology gets complex or when your node reconnects after some time offline, Syncthing synchronises with its neighbours: It gets the latest synchronised state from the neighbour, which is the result of all the changes between the last known state (before disconnect or network delay) and the current state at the neighbour, and if there were updates, deletes, creates, conflicts, which were overlapping we only see the latest change for a given file or directory (and the node where that latest change occurred). When we connect to multiple neighbours Syncthing decides which neighbour has the latest state, or if the states conflict it initiates the conflict resolution procedure, which in the end results in a consistent up-to-date state with all the neighbours.

### Why does Syncthing connect to this unknown/suspicious address?
If you see outgoing connections to odd and unexpected addresses these are most likely connections to relay servers. Relay servers are run by volunteers all over the world. They usually listen on ports 443 or 22067, though this is controlled by the user running it. You can compare the address you are concerned about with the current list of active relays <https://relays.syncthing.net>. Relays do not and can not see the data transmitted via them.

### I am seeing the error message “folder marker missing”. What do I do?
Syncthing uses a specific marker usually called .stfolder to determine whether a folder is healthy. This is a safety check to ensure that your folder is properly readable and present on disk. For example, if you remove a USB drive from your computer or unmount a filesystem, then syncthing must know whether you have really deleted all of your files. Therefore, syncthing always checks that the .stfolder is present.

When this error appears, syncthing assumes that the folder has encountered some type of error and will stop syncing it until the .stfolder reappears. Once that happens, all changes made to the folder locally will be synced (i.e. missing files will be considered deletions).

- If you get this error message, check the folder in question on your storage. If you have unmounted the folder (or a parent of it), you must remount it for syncthing to resume syncing this folder.

- If you have moved the folder, you must either move it back to its original location, or remove the folder from within the syncthing UI and re-add it at its new location.

- If the folder is present on disk, with all of its children files and directories, but the .stfolder is still missing: It is possible that a file cleaning software has removed the .stfolder. Some software removes empty folders, and the .stfolder is often empty. This happens particularly often on Android. To remediate, recreate the .stfolder and add a dummy file in it, or add an exception to your cleaning software.

If you are still unsure what has happened, you can remove the folder from within the syncthing UI and re-add it at the same location. This causes syncthing to attempt an automatic re-creation of the .stfolder. Next, it will also reset the database state of this folder. It will be considered a “new” folder, meaning that its files will be merged with files from remote devices.

Also see the marker FAQ for more information about the folder marker.

### Why do my Windows computers always connect through a relay?
When connecting to a new network, Windows by default sets its profile to “Public”. While being more secure, this setting commonly prevents applications like Syncthing from being able to establish direct connections with the device in question, forcing it to connect through a relay. If you would rather connect your devices directly, please follow the official Microsoft instructions on how to change the network profile to “Private” <https://support.microsoft.com/windows/essential-network-settings-and-tasks-in-windows-f21a9bbc-c582-55cd-35e0-73431160a1b9#bkmk_network_profile>.

## USAGE

### What if there is a conflict?
SEE ALSO:

Conflicting Changes

### How do I serve a folder from a read only filesystem?
Syncthing requires a “folder marker” to indicate that the folder is present and healthy. By default this is a directory called .stfolder that is created by Syncthing when the folder is added. If this folder can’t be created (you are serving files from a CD or something) you can instead set the advanced config Marker Name to the name of some file or folder that you know will always exist in the folder.

### I really hate the .stfolder directory, can I remove it?
See the previous question.

### Am I able to nest shared folders in Syncthing?
Sharing a folder that is within an already shared folder is possible, but it has its caveats. What you must absolutely avoid are circular shares. This is just one example, there may be other undesired effects. Nesting shared folders is not supported, recommended or coded for, but it can be done successfully when you know what you’re doing - you have been warned.

### How do I rename/move a synced folder?
Syncthing doesn’t have a direct way to do this, as it’s potentially dangerous to do so if you’re not careful - it may result in data loss if something goes wrong during the move and is synchronized to your other devices.

The easy way to rename or move a synced folder on the local system is to remove the folder in the Syncthing UI, move it on disk, then re-add it using the new path.

It’s important to do this when the folder is already in sync between your devices, as it is otherwise unpredictable which changes will “win” after the move. Changes made on other devices may be overwritten, or changes made locally may be overwritten by those on other devices.

An alternative way is to shut down Syncthing, move the folder on disk (including the .stfolder marker), edit the path directly in config.xml in the configuration folder (see Syncthing Configuration) and then start Syncthing again.

### How do I configure multiple users on a single machine?
Each user should run their own Syncthing instance. Be aware that you might need to configure listening ports such that they do not overlap (see Syncthing Configuration).

### Does Syncthing support syncing between folders on the same system?
No. Syncthing is not designed to sync locally and the overhead involved in doing so using Syncthing’s method would be wasteful. There are better programs to achieve this such as rsync <https://rsync.samba.org/> or Unison <https://www.cis.upenn.edu/~bcpierce/unison>.

### When I do have two distinct Syncthing-managed folders on two hosts, how does Syncthing handle moving files between them?
Syncthing does not specially handle this case, and most files will most likely get re-downloaded.

In detail, the behavior depends on the scan order. If you have folders A and B, and move files from A to B, if A gets scanned first, it will announce the removal of the files to others who will then remove the files. As you rescan B, B will announce the addition of new files, and other peers will have nowhere to get them from apart from re-downloading them.

If B gets rescanned first, B will announce additions first, and remote peers will then reconstruct the files (not rename, more like copying block by block) from A, and then as A gets rescanned, it will remove the files from A.

A workaround would be to copy first from A to B, rescan B, wait for B to copy the files on the remote side, and then delete from A.

### Can I help initial sync by copying files manually?
If you have a large folder that you want to keep in sync over a not-so-fast network, and you have the possibility to move all files to the remote device in a faster manner, here is a procedure to follow:

- Create the folder on the local device, but don’t share it with the remote device yet.

- Copy the files from the local device to the remote device using regular file copy. If this takes a long time (perhaps requiring travelling there physically), it may be a good idea to make sure that the files on the local device are not updated while you are doing this.

- Create the folder on the remote device, and copy the Folder ID from the folder on the local device, as we want the folders to be considered the same. Then wait until scanning the folder is done.

- Now share the folder with the other device, on both sides. Syncthing will exchange file information, updating the database, but existing files will not be transferred. This may still take a while initially, be patient and wait until it settled.

### Is Syncthing my ideal backup application?
No. Syncthing is not a great backup application because all changes to your files (modifications, deletions, etc.) will be propagated to all your devices. You can enable versioning, but we encourage you to use other tools to keep your data safe from your (or our) mistakes.

### How can I exclude files with brackets ([]) in the name?
The patterns in .stignore are glob patterns, where brackets are used to denote character ranges. That is, the pattern q[abc]x will match the files qax, qbx and qcx.

To match an actual file called q[abc]x the pattern needs to “escape” the brackets, like so: q\[abc\]x.

On Windows, use the | character to escape the brackets (q|[abc|]x), as the \ character is used as a path separator.

### How do I access the web GUI from another computer?
The default listening address is 127.0.0.1:8384, so you can only access the GUI from the same machine. This is for security reasons. To access it from another computer, change the GUI listen address option in the web GUI from 127.0.0.1:8384 to 0.0.0.0:8384, or change the config.xml:

```
<gui enabled="true" tls="false">

  <address>127.0.0.1:8384</address>
```

to

```
<gui enabled="true" tls="true">

  <address>0.0.0.0:8384</address>
```

Then the GUI is accessible from everywhere. There is no filtering based on e.g. source address (use a firewall for that). You should set a password and enable HTTPS with this configuration. You can do this from inside the GUI.

If both your computers are Unix-like (Linux, Mac, etc.) you can also leave the GUI settings at default and use an SSH port forward to access it. For example,

```
$ ssh -L 9090:127.0.0.1:8384 user@othercomputer.example.com
```

will log you into othercomputer.example.com, and present the remote Syncthing GUI on http://localhost:9090 on your local computer.

If you only want to access the remote GUI and don’t want the terminal session, use this example:

```
$ ssh -N -L 9090:127.0.0.1:8384 user@othercomputer.example.com
```

If only your remote computer is Unix-like, you can still access it with SSH from Windows. Under Windows 10 or later you can use the same ssh command if you install the OpenSSH Client <https://learn.microsoft.com/windows-server/administration/openssh/openssh_install_firstuse>.

### I don’t like the GUI or the theme. Can it be changed?
You can change the theme in the settings. Syncthing ships with other themes than the default.

If you want a custom theme or a completely different GUI, you can add your own. By default, Syncthing will look for a directory gui inside the Syncthing home folder. To change the directory to look for themes, you need to set the STGUIASSETS environment variable. To get the concrete directory, run syncthing with the --paths parameter. It will print all the relevant paths, including the “GUI override directory”.

To add e.g. a red theme, you can create the file red/assets/css/theme.css inside the GUI override directory to override the default CSS styles.

To create a whole new GUI, you should checkout the files at https://github.com/syncthing/syncthing/tree/main/gui/default to get an idea how to do that.

### How do I upgrade Syncthing?
If you use a package manager such as Debian’s apt-get, you should upgrade using the package manager. If you use the binary packages linked from Syncthing.net, you can use Syncthing’s built-in automatic upgrade functionality.

- If automatic upgrades is enabled (which is the default), Syncthing will upgrade itself automatically within 24 hours of a new release.

- The upgrade button appears in the web GUI when a new version has been released. Pressing it will perform an upgrade.

- To force an upgrade from the command line, run syncthing --upgrade.

Note that your system should have CA certificates installed which allows a secure connection to GitHub (e.g. FreeBSD requires sudo pkg install ca_root_nss). If curl or wget works with normal HTTPS sites, then so should Syncthing.

### Where do I find the latest release?
We release new versions through GitHub. The latest release is always found on the release page <https://github.com/syncthing/syncthing/releases/latest>. Unfortunately GitHub does not provide a single URL to automatically download the latest version. We suggest to use the GitHub API <https://api.github.com/repos/syncthing/syncthing/releases/latest> and parsing the JSON response.

### How do I run Syncthing as a daemon process on Linux?
If you’re using systemd, runit, or upstart, we ship example configurations <https://github.com/syncthing/syncthing/tree/main/etc>.

If however you’re not using one of these tools, you have a couple of options. If your system has a tool called start-stop-daemon installed (that’s the name of the command, not the package), look into the local documentation for that, it will almost certainly cover 100% of what you want to do. If you don’t have start-stop-daemon, there are a bunch of other software packages you could use to do this. The most well known is called daemontools, and can be found in the standard package repositories for almost every modern Linux distribution. Other popular tools with similar functionality include S6 and the aforementioned runit.

### How do I increase the inotify limit to get my filesystem watcher to work?
You are probably reading this because you encountered the following error with the filesystem watcher on linux:

Failed to start filesystem watcher for folder yourLabel (yourID): failed to set up inotify handler. Please increase inotify limits, see https://docs.syncthing.net/users/faq.html#inotify-limits

Linux typically restricts the number of watches per user (usually 8192). If you have many directories, you will need to adjust that number.

On many Linux distributions you can run the following to fix it:

```
echo "fs.inotify.max_user_watches=204800" | sudo tee -a /etc/sysctl.conf
```

On Arch Linux and potentially others it is preferred to write this line into a separate file, i.e. you should run:

```
echo "fs.inotify.max_user_watches=204800" | sudo tee -a /etc/sysctl.d/90-override.conf
```

This only takes effect after a reboot. To adjust the limit immediately, run:

```
echo 204800 | sudo tee /proc/sys/fs/inotify/max_user_watches
```

### How do I reset the GUI password?
If you’ve forgotten / lost the GUI password, you can reset it using the --gui-password (and possibly --gui-user) options to the syncthing generate subcommand. This should be done while Syncthing is not running.

1.

Stop Syncthing: syncthing cli operations shutdown

2.

syncthing generate --gui-password=myNewPassword --gui-user=newUserName

3.

Restart Syncthing as usual.

Alternatively, in step 2, you can manually delete the <user> and <password> XML tags from the <gui> block in file config.xml. The location of the file depends on the OS and is described in the configuration documentation.

For example, the two emphasized lines below would be removed from the file.

```
<gui enabled="true" tls="false">

   <address>127.0.0.1:8384</address>

   <user>syncguy</user>

   <password>$2a$10$s9wWHOQe...Cq7GPye69</password>

   <apikey>9RCKohqCAyrj5RjpyZdR2wXmQ9PyQFeN</apikey>

   <theme>default</theme>
</gui>
```

## AUTHOR
The Syncthing Authors

## COPYRIGHT
2014-2026, The Syncthing Authors


syncthing-globaldisco

title: syncthing-globaldisco(7)

summary: Global Discovery Protocol v3

text:
# syncthing-globaldisco(7)

## NAME
syncthing-globaldisco - Global Discovery Protocol v3

## ANNOUNCEMENTS
A device should announce itself at startup. It does this by an HTTPS POST to the announce server URL. Standard discovery currently requires the path to be “/v2/”, yet this can be up to the discovery server. The POST has a JSON payload listing connection addresses (if any):

```
{

        addresses: ["tcp://192.0.2.45:22000", "tcp://:22202", "relay://192.0.2.99:22028"],
}
```

It’s OK for the “addresses” field to be either the empty list ([]), null, or missing entirely. An announcement with the field missing or empty is however not useful…

Any empty or unspecified IP addresses (i.e. addresses like tcp://:22000, tcp://0.0.0.0:22000, tcp://[::]:22000) are interpreted as referring to the source IP address of the announcement.

The device ID of the announcing device is not part of the announcement. Instead, the server requires that the client perform certificate authentication. The device ID is deduced from the presented certificate.

The server response is empty, with code 204 (No Content) on success. If no certificate was presented, status 403 (Forbidden) is returned. If the posted data doesn’t conform to the expected format, 400 (Bad Request) is returned.

In successful responses, the server may return a Reannounce-After header containing the number of seconds after which the client should perform a new announcement.

In error responses, the server may return a Retry-After header containing the number of seconds after which the client should retry.

Performing announcements significantly more often than indicated by the Reannounce-After or Retry-After headers may result in the client being throttled. In such cases the server may respond with status code 429 (Too Many Requests).

## QUERIES
Queries are performed as HTTPS GET requests to the announce server URL. The requested device ID is passed as the query parameter “device”, in canonical string form, i.e. https://discovery.syncthing.net/?device=ABC12345-....

Successful responses will have status code 200 (OK) and carry a JSON payload of the same format as the announcement above. The response will not contain empty or unspecified addresses.

If the “device” query parameter is missing or malformed, the status code 400 (Bad Request) is returned.

If the device ID is of a valid format but not found in the registry, 404 (Not Found) is returned.

If the client has exceeded a rate limit, the server may respond with 429 (Too Many Requests).

## AUTHENTICATION
Global discovery is spoken over HTTPS and is protected against attackers in the same manner as other HTTPS traffic. However, there are a few Syncthing specific considerations on top of this. As mentioned above, for announcements the client must provide a certificate to prove ownership of the announced device ID.

In addition, Syncthing has a mechanism to verify the identity of the discovery server. While this would normally be accomplished by using a CA signed certificate, Syncthing often runs in environments with outdated or simply nonexistent root CA bundles. Instead, Syncthing can verify the discovery server certificate fingerprint using the device ID mechanism. This is certificate pinning and conveyed in the Syncthing configuration as a synthetic “id” parameter on the discovery server URL: https://discovery.syncthing.net/?id=.... The “id” parameter is not, in fact, sent to the discovery server - it’s used by Syncthing itself to know which certificate to expect on the server side.

The public discovery network uses this authentication mechanism instead of CA signed certificates.

The discovery server prints its certificate ID in this manner on startup.

## AUTHOR
The Syncthing Authors

## COPYRIGHT
2014-2026, The Syncthing Authors


syncthing-localdisco

title: syncthing-localdisco(7)

summary: Local Discovery Protocol v4

text:
# syncthing-localdisco(7)

## NAME
syncthing-localdisco - Local Discovery Protocol v4

## MODE OF OPERATION
Each participating device periodically sends an Announcement packet. It also keeps a table of the announcements it has seen. There is no way to solicit a reply; the only message type is Announcement.

On multihomed hosts the announcement packets should be sent on each interface on which Syncthing will accept connections.

The announcement packet is sent over UDP.

For IPv4, the Announcement packet is broadcast either to the link-specific broadcast address, or to the generic link-local broadcast address 255.255.255.255, with destination port 21027.

For IPv6, the Announcement packet is multicast to the transient link-local multicast address ff12::8384, with destination port 21027.

It is recommended that local discovery Announcement packets be sent on a 30 to 60 second interval, possibly with immediate transmissions when a previously unknown device is discovered or a device has restarted (see the instance_id field).

## DEVICE ID
The device ID is the SHA-256 (32 bytes) of the device X.509 certificate. See Understanding Device IDs in the Syncthing documentation.

## ANNOUNCEMENT PACKET
The Announcement packet has the following structure:

```
 0                   1                   2                   3

 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                             Magic                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/                                                               /
\                       Announce Message                        \
/                                                               /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
```

There is no explicit length field as the length is given by the length of the discovery announcement packet itself.

The Magic field is a 32 bit word representing 0x2EA7D90B in network (big endian) byte order. It identifies the packet as being a Syncthing discovery protocol packet.

The Announce Message contents are in protocol buffer format using the following schema:

```
message Announce {

    bytes           id          = 1;

    repeated string addresses   = 2;

    int64           instance_id = 3;
}
```

The id field contains the Device ID of the sending device.

The addresses field contains a list of addresses where the device can be contacted. Direct connections will typically have the tcp:// scheme. Relay connections will typically use the relay:// scheme.

When interpreting addresses with an unspecified address, e.g., tcp://0.0.0.0:22000 or tcp://:42424, the source address of the discovery announcement is to be used.

The instance_id field is set to a randomly generated ID at client startup. Other devices on the network can detect a change in instance ID between two announces and conclude that the announcing device has restarted.

## AUTHOR
The Syncthing Authors

## COPYRIGHT
2014-2026, The Syncthing Authors