Syncthing

Posted on Thu 11 October 2018 in linux

Syncthing is an open-source synchronization tool that allows the decentralized sharing of files between devices. In contrast to other synchronization services that store your data somewhere on servers in the cloud, Syncthing operates in a P2P-fashion, i.e. without such a central server, by just transmitting the data between your own devices directly. All of the used communication is encrypted via TLS to prevent eavesdroppers to gain access to the data. Besides, all participating devices must be authenticated via a strong cryptographic certificate so that only explicitly allowed devices can join the synchronization.

Since Syncthing is implemented in go it is available for all major operating systems, including Linux, Windows, MacOS, BSD-Variants. Apart from this there is also an Android App to sync files to mobile devices.

In the following, an advanced Syncthing setup is discussed that focuses on the current Debian version Stretch.

Base Setup

Since Debian packages tend to become outdated fast, while Syncthing is under heavy development, it is recommended to make use of the latest Syncthing version. Luckily, Syncthing provides its own Debian repository that can be easily integrated as follows:

# make sure that https transport is supported
sudo apt install apt-transport-https

# add the Syncthing's developers gpg key
curl -s https://syncthing.net/release-key.txt | sudo apt-key add -

# Add the "stable" channel to the APT sources:
echo "deb https://apt.syncthing.net/ syncthing stable" | sudo tee /etc/apt/sources.list.d/syncthing.list

# Update and install Syncthing:
sudo apt update

Syncthing client

To synchronize files the Syncthing client must be installed on two or more devices. The client can simply be installed as follows:

sudo apt install syncthing

Afterwards, the application can be started by calling syncthing. The application will fire up and open the port 8384 that provides a webpage that can be locally access by pointing the browser to http://127.0.0.1:8384 (on a desktop system the webpage will automatically be opened by the default browser).

For the configuration of the web application check out the official Syncthing introduction.

Since for testing purposes this is nice, normally a syncing service should run in the background. A simple way to pursue this is to setup a systemd service for your user with the by Syncthing provided service files.

# start the service and make sure it runs correctly
sudo systemctl start syncthing@myuser.service
sudo systemctl status syncthing@myuser.service

# enable the service for an automatic start on boot
sudo systemctl enable syncthing@myuser.service

If you are only using Syncthing locally, just configure the shared directories via the webpage. In the case that you want to expose the Syncthing port to a network, make sure to set a password for the web UI and to enable https support in the settings.

Additional Services

When files should be synchronized between devices that are located in different subnetworks, the devices can neither locally detect whether they are online or not nor exchange data. Syncthing provides two mechanisms to circumvent these problems: the discovery server and the relay server. While the discovery server allows a device to state its current online status and reply the status to other devices on request, the relay server deals with the intermediate relaying of data packets between two devices that cannot directly reach each other. Although, Syncthing provides both services for all users and all of the communication is end-to-end encrypted, you may become paranoid to share those services with all the other users. Alternatively, Syncthing provides complementary to the client both other services as well for a setup in custom environments so that individual discovery and relay services can be setup for private use.

For that reason, in the following, the private setup of the discovery server and the relay server are discussed for the paranoids of us ;-)

Prerequisites

Since it is strongly discouraged to run such services as root user, a dedicated syncthing user is created as follows:

sudo useradd -r -s /bin/false syncthing

The user will just be used to run the services, so the user can neither login nor a home directory is provided.

Moreover, a corresponding directory for the data is created and the permissions are set for the new user:

sudo mkdir /var/lib/syncthing
sudo chown syncthing:root /var/lib/syncthing

When using letsencrypt certificates ensure that the syncthing user can access the corresponding certificates. This can, for example, be implemented by adding the user to the ssl-cert group and adapting the directory permissions correspondingly.

sudo adduser syncthing ssl-cert
sudo chown root:ssl-cert /etc/letsencrypt/{archive,live}
sudo chmod g+xr /etc/letsencrypt/{archive,live}

Discovery Server

Using the Debian repository, the discovery server can be installed as follows:

sudo apt install syncthing-discosrv

To run the discovery server in the background with the syncthing user, a new system service will be created. Sadly, there is no template so a custom service must be defined:

A new /etc/systemd/system/stdiscosrv.service file is created with the following content:

[Unit]
Description=Syncthing Discovery Service (stdiscosrv)
After=network.target

[Service]
Type=simple
User=syncthing
ExecStart=/usr/bin/stdiscosrv -cert /etc/letsencrypt/live/<mydomain>/fullchain.pem -key /etc/letsencrypt/live/<mydomain>/privkey.pem -db-dir /var/lib/syncthing/discosrv.db -http
Restart=on-failure
SuccessExitStatus=2

PrivateDevices=true
ProtectSystem=full
ProtectHome=true
NoNewPrivileges=true

[Install]
WantedBy=multi-user.target

Make sure to adapt the certificate and private key for the file.

Start the service:

# reload the systemd files
systemctl daemon-reload

# start the discovery service and make sure that it runs correctly
sudo systemctl start stdiscosrv
sudo systemctl status stdiscosrv

# start the service on next boot automatically
sudo systemctl enable stdiscosrv

For a simple access a reverse proxy for nginx is configured. Create the /etc/nginx/sites-available/disco site file with the following content:

# HTTP 1.1 support
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $proxy_connection;
proxy_set_header X-SSL-Cert $ssl_client_cert;
upstream disco.yourdomain.de {
    # Local IP address:port for discovery server
    server 127.0.0.1:8443;
}
server {
        server_name disco.yourdomain.de;
        listen 80;
        return 301 https://$host$request_uri;
}
server {
        server_name disco.yourdomain.de;
        listen 443 ssl http2;
        ssl_protocols TLSv1.2;
        ssl_ciphers 'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4';
        ssl_prefer_server_ciphers on;
        ssl_session_timeout 5m;
        ssl_session_cache shared:SSL:50m;
        ssl_certificate /etc/letsencrypt/live/<yourdomain>/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/<yourdomain>/privkey.pem;
        ssl_dhparam /etc/nginx/ssl/dhparam.pem;
        add_header Strict-Transport-Security "max-age=31536000";
        ssl_verify_client optional_no_ca;
        location / {
                proxy_pass http://disco.yourdomain.de;
        }
}

Make sure to adapt the domain and your certificate details. Then, activate the nginx page and restart the server.

ln -s /etc/nginx/sites-available/disco /etc/nginx/sites-enabled/disco
systemctl restart nginx

The discovery https://disco.yourdomain.de can now be set in the client's configuration.

Relay Server

Similarly, the relay server can be installed using the Debian repository:

sudo apt install syncthing-relaysrv

Create a new /etc/systemd/system/strelaysrv.service file with the following content:

[Unit]
Description=Syncthing Relay Service (strelaysrv)
After=network.target

[Service]
Type=simple
User=syncthing
ExecStart=/usr/bin/strelaysrv -keys /var/lib/syncthing -pools=""
Restart=on-failure
SuccessExitStatus=2

PrivateDevices=true
ProtectSystem=full
ProtectHome=true
NoNewPrivileges=true

[Install]
WantedBy=multi-user.target

The pools="" ensures that the relay server stays private and does not join other existing default pools.

Start the service:

# reload the systemd files
systemctl daemon-reload

# start the relay service and make sure that it runs correctly
sudo systemctl start strelaysrv
sudo systemctl status strelaysrv

# start the service on next boot automatically
sudo systemctl enable strelaysrv

You can check the relay server by visiting http://:22070/status with your webbrowser.

The client needs to be pointed to access the relay server.

relay://<yourdomain>:22069/?id=<your ID>

Disclaimer

This setup was written based on an already running server so that there might be steps that I forgot to mention here. Feel free to contact me if there are any problems with this tutorial.

Besides, check the official documentation on https://docs.syncthing.net to get more information about the configuration details.