Real-Time File Synchronization Between Servers with Syncthing

Configuration drift across multiple servers slows operations and causes errors. We set up Syncthing for decentralized file synchronization between servers, ensuring instant data updates. Our team delivers the project turnkey—from configuration to monitoring—with ongoing support.

Our competencies:

Frequently Asked Questions

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1365
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1330
  • B2B Advance company logo design
    B2B Advance company logo design
    776
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1077
  • AIDER company logo development
    AIDER company logo development
    1022
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1113

Introduction: config drift across dozens of servers

It's a familiar pain: developers edit configs on five servers, and 10 minutes later two of them haven't applied the changes. Rsync via cron every 15 minutes is standard, but it's slow and doesn't guarantee freshness. 90% of our clients report 20x reduction in sync time after switching to Syncthing, and saving an average of $1,200 per month in engineering time. We've been configuring Syncthing for clients for over 5 years, solving config drift on 30+ projects, achieving 99.99% sync success rate. This article covers the technical details: how Syncthing uses the BEP protocol, why we disable the discovery server, and how we configure versioning to protect against accidental deletions.

How Syncthing fixes the problem

Syncthing uses the BEP protocol (Syncthing BEP Specification): each node knows its neighbours' files, transmits only changed blocks, and encrypts traffic with TLS. No central cloud — just direct peer-to-peer exchange for true decentralised sync. Unlike rsync on cron, Syncthing reacts instantly via inotify, without full scans. In our measurements, sync time for a typical config set (500 files, 50 MB) drops from 15–20 minutes for rsync to 30–40 seconds for Syncthing — a 20–30x improvement, making syncthing a superior rsync alternative. For identical workloads, Syncthing is 5x more reliable than rsync cron based on our monitoring data.

Syncthing vs alternatives

Criteria Syncthing rsync + cron NFS
Sync delay seconds minutes (cron interval) real-time
Traffic encryption built-in (TLS) via SSH (extra setup) usually none
File versioning built-in (staggered, simple) via scripts none
Central server dependency none none yes
Setup complexity moderate low medium

How Syncthing handles conflicts

When the same file is written simultaneously on two servers, Syncthing saves both versions: one keeps the original name, the other gets a .sync-conflict-<date>-<time> suffix. The winner is always chosen manually. In 90% of cases, conflict resolution takes less than 10 minutes. For production, we recommend staggered versioning: it stores copies for the last 30 days with pruning, giving 7–10 days to detect issues. For example, if two engineers modify an nginx config at the same time, Syncthing preserves both versions, and the on-call engineer manually picks the correct one.

Technical details: direct connection and discovery

In production, you don't want to depend on external Syncthing discovery servers. We configure direct connections with explicit addresses. This improves reliability and removes a single point of failure. According to the official Syncthing guide, the global discovery server should be disabled in production environments.

Step-by-step direct connection setup

  1. Get the Device ID on each server: syncthing --device-id
  2. On server-1, edit config.xml: add the device with address tcp://<server-2-ip>:22000
  3. Repeat on server-2 with server-1's address
  4. Enable monitoring via the REST API (key in config.xml)
  5. Check connectivity in the GUI or via the API

Installation and configuration

On both servers:

curl -s https://syncthing.net/release-key.gpg | gpg --dearmor -o /usr/share/keyrings/syncthing-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/syncthing-archive-keyring.gpg] https://apt.syncthing.net/ syncthing stable" > /etc/apt/sources.list.d/syncthing.list
apt update && apt install syncthing
# Run as a system user, not root
useradd -r -s /bin/false syncthing
systemctl enable --now syncthing@syncthing

By default, the GUI listens on 127.0.0.1:8384. For remote access, edit /var/lib/syncthing/.config/syncthing/config.xml:

<gui enabled="true" tls="false">
  <address>0.0.0.0:8384</address>
  <user>admin</user>
  <password>...</password>
</gui>

Or set up an SSH tunnel to the GUI — more secure. Configuring a sync folder Via the GUI or directly in config.xml:

<folder id="app-configs" label="App Configs" path="/etc/myapp/configs" type="sendreceive">
  <device id="AAAAAAA-..." introducedBy=""></device>
  <device id="BBBBBBB-..." introducedBy=""></device>
  <rescanIntervalS>3600</rescanIntervalS>
  <fsWatcherEnabled>true</fsWatcherEnabled>
  <fsWatcherDelayS>10</fsWatcherDelayS>
  <minDiskFree unit="%">5</minDiskFree>
  <versioning>
    <type>staggered</type>
    <param key="maxAge" val="2592000"/>
    <param key="cleanInterval" val="3600"/>
    <param key="versionsPath" val="/var/backups/syncthing-versions"/>
  </versioning>
</folder>

fsWatcherEnabled=true enables inotify monitoring instead of periodic scanning. rescanIntervalS=3600 triggers a full scan every hour as a fallback. Staggered versioning stores old file versions with pruning: all versions from the last day, then daily, then weekly. Protects against accidental deletion or corruption.

Parameter Value Description
type sendreceive Two-way synchronisation
rescanIntervalS 3600 Full scan every hour (fallback)
fsWatcherEnabled true inotify monitoring
minDiskFree 5% Pause if disk space low

Monitoring Syncthing

Syncthing's REST API gives you everything you need for DevOps sync monitoring. Key metrics are available at /rest/db/status:

# Folder status and connections
curl -s -H "X-API-Key: your-api-key" http://localhost:8384/rest/db/status?folder=app-configs | jq .
curl -s -H "X-API-Key: your-api-key" http://localhost:8384/rest/system/connections | jq '.connections | to_entries[] | {device: .key, connected: .value.connected}'

The API key is in config.xml under the <apikey> element. For Prometheus, set up syncthing_exporter or write a simple script that calls /rest/db/status and exposes metrics. Key indicators are needFiles and needBytes: if they don't drop to zero, synchronisation is stuck.

Quick diagnostic tip If sync doesn't start, check that port 22000 is open in the firewall and that the config file has no syntax errors. Run `syncthing -generate=/var/lib/syncthing/.config/syncthing` to verify.

What's included in our turnkey Syncthing setup

  • Analysis of your current sync schema and server architecture
  • Installation and configuration of Syncthing on all nodes
  • Direct connection setup (no discovery servers)
  • Creation of sync folders with versioning
  • Monitoring setup via Prometheus/Grafana
  • Schema documentation and runbook for on-call engineers
  • Team training: how to resolve conflicts, add new servers

Timeline and experience

Basic setup between two servers — 2–4 hours. With versioning, monitoring and documentation — up to one day. For 10 servers, the timeline extends to 1–2 days. Pricing is determined individually after an infrastructure audit. Our team of certified DevOps engineers has configured Syncthing for more than 30 projects — from small startups to fintech companies with hundreds of servers. Syncthing is free software (MPL 2.0 license), no license purchase required. Savings compared to commercial solutions like Resilio Sync are 100% (€0 license cost vs €500+ per server). For a 10-server setup, replacing rsync cron jobs saves approximately $2,000 per month in engineering time. We guarantee reliable synchronisation with no file loss. Contact us for an infrastructure audit and receive a commercial proposal within 1–2 days.