Skip to main content

Syncthing

The kasad.com server runs a Syncthing relay server and discovery server. These services enable completely private file syncing by removing reliance on Syncthing's public servers for discovery and relaying.

Purpose

Each server provides a method of communication for devices running Syncthing on separate networks.

Relay server

When two Syncthing instances (i.e. two separate devices) cannot establish a direct connection, they must use relaying. Both clients will connect to a publicly-accessible relay server and use it to transfer data between the two clients.

Discovery server

When Syncthing instances are on the same LAN, they can discover each other using broadcast or multicast network traffic. When they are on separate networks, they require a discovery server. Each client connects to the discovery server and informs it of its IP address. The discovery server can then inform the clients of each other's location.

Running the services

Syncthing has tutorials as part of their documentation for running your own relay server or discovery server. Regardless, I'll explain the process here.

Install the daemons

Both servers are distributed as Debian packages, which is what I'll use since the kasad.com server runs Debian.

Just install the syncthing-discosrv and syncthing-relayserv packages:

# nala install syncthing-{relay,disco}srv

Configuring the discovery server

There is no configuration file for syncthing-discosrv. It only accepts command-line arguments. We can provide those using the STDISCOSRV_OPTS environment variable in the /etc/default/syncthing-discosrv file:

STDISCOSRV_OPTS="-http"

We'll only enable the -http option, as we'll use our NGINX server as a reverse proxy for HTTPS.

Setting up the reverse proxy

Since we only want to allow secure connections, we need an HTTPS reverse proxy in front of the discovery server. We can easily do this with NGINX using the following server configuration:

server {
	listen 80;
	listen [::]:80;
	server_name stdisco.kasad.com;

	return 301 https://$host$request_uri;
	
	include /etc/nginx/conf.d/common;
	include /etc/nginx/conf.d/common-kasad.com;
}

server {
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
	server_name stdisco.kasad.com;

	try_files $uri =503;

	ssl_verify_client optional_no_ca;

	location / {
        proxy_http_version 1.1;
        proxy_buffering off;
        proxy_set_header Host $http_host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $http_connection;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Client-Port $remote_port;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
        proxy_set_header X-SSL-Cert $ssl_client_cert;
		proxy_pass http://localhost:8443/;
	}

	include /etc/nginx/conf.d/common;
	include /etc/nginx/conf.d/common-kasad.com;
	include /etc/nginx/conf.d/common-kasad.com-ssl;
}

This file gets placed in /etc/nginx/sites-enabled. This will make the discovery server available at stdisco.kasad.com.

A better way to handle NGINX site configurations is to place all files in /etc/nginx/sites-available, then place a symbolic link in /etc/nginx/sites-enabled that points to ../sites-available/<site>.

Configuring the relay server

The relay server uses its own application protocol, so it's a little easier to configure. This time, we'll define two variables in /etc/default/syncthing-relaysrv:

NAT=false
STRELAYSRV_OPTS=-pools="" -provided-by="Kian Kasad - https://kasad.com" -ext-address=kasad.com:22067

Check the systemd.exec(5) manual page for details on the environment file syntax, as it's a little different from standard shell syntax.

The first line in our file disables Network Address Translation, as the kasad.com server already has a public IP address.

The second line sets the command-line options:

  • -pools="" disables joining the default relay pool, meaning our relay server won't be available to the general public.
  • -provided-by-"Kian Kasad - https://kasad.com" sets the Provided By description for our server.
  • -ext-address=kasad.com:22067 tells the relay server to use the external address kasad.com:22067 when printing the URI that clients will use to connect to the server.

Firewall rules

The relay server listens on TCP port 22067 by default. We need to add a firewall rule to allow incoming traffic on this port. Since the kasad.com server runs nftables, we'll add a rule to our /etc/nftables.conf file:

table inet filter {
    chain input {
    	tcp dport 22067 accept comment "Syncthing relay server"
    }
}

Enable the services

Both packages provide Systemd services, so we can just enable and start those:

# systemctl enable --now syncthing-{relay,disco}srv.service

Client configuration

To use these servers from a Syncthing client, we need to change a few settings.

Using the discovery server

This is the easier of the two services to configure. Just open Syncthing's settings menu and navigate to the Connections tab. Then set https://stdisco.kasad.com/ as the value for the Global Discovery Servers option.

Using the relay server

The relay server takes a little more configuration for the client to use. You must first find the URI to use to connect to the relay server. This is printed when it starts, so we can look in systemd's logs:

# journalctl -eu syncthing-relaysrv.service

Find the line that contains URI: followed by a string. Copy that value, as that's the URI you need to use.

Then open Syncthing's settings page and go to the Connections tab. Add a comma after the current value of the Sync Protocol Listen Addresses option and paste your relay server's URI in.

If the Sync Protocol Listen Addresses option has the default value, replace that with tcp://:22000, quic://:22000. This is because the default value will also use Syncthing's public relay servers, which we don't want.